/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2002 * Copyright by ESO (in the framework of the ALMA collaboration) * and Cosylab 2002, All rights reserved * * 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; either * version 2.1 of the License, or (at your option) any later version. * * 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. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package com.cosylab.logging; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Vector; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; /** * The widget reporting messages. *
* This widget is invisible and appears only when a message must be notified
* to the user.
* When the user presses the Ok button, the panel hides itself.
* The method removeError()
allows to hide the panel programmatically.
*
* The look of the panel changes if a detailed description of the error is present.
* If it is the case, the panel shows a title label on top.
* If instead the detailed description is not defined, then the label and the detailed panel are hidden.
* This allows to use the component as "light" or "heavy" by setting a detailed description.
* Which of the two modality is in use is returned by the boolean
of the two showMessage(...)
methods.
*
* @author acaproni
*
*/
public class MessageWidget extends JPanel {
/**
* The type of the message shown by the glass pane
*
* @author acaproni
*
*/
public enum MessageType {
Error("dialog-error.png"),
Warning("dialog-warning.png"),
Info("dialog-information.png");
/**
* The icon shown for each type of dialog
*
*/
public final ImageIcon icon;
/**
* Constructor
*
* @param iconPath
*/
private MessageType(String iconPath) {
icon=new ImageIcon(MessageWidget.class.getResource("/"+iconPath));
}
};
/**
* The listener to be notified when the user acknowledge
* the message by pressing the button
*
* @author acaproni
*
*/
public interface MessageWidgetListener {
public void errorAcknowledged();
}
/**
* The text describing the problem
*/
private final JLabel shortDescriptionLbl=new JLabel();
/**
* The text to give a detailed description of the problem.
*/
private final JTextArea detailedDescritpionTA= new JTextArea();
/**
* The panel with the detailed description of the problem.
*
* This component appears only if it is not empty. */ private JScrollPane detailedDescPnl; /** * The icon */ private final JLabel iconLbl = new JLabel(); /** * The title of the error. *
* The title is displayed on top but only if the detailed description is present.
*/
private final JLabel titleLbl = new JLabel();
/**
* The button to acknowledge the message
*/
private final JButton ackBtn = new JButton("Ok");
/**
* The listeners to be notified when the user acknowledges the message
*/
private Collection
* The message type and the short description are mandatory to present to the user the
* message.
* A detailed description can also be given to better explain what's going on. It might be
* a stack trace, for example.
*
* @param messageType The type of the message
* @param shortDescription A short description of the message
* @param description The detailed description; it can be
* This method shows an error message, by setting the stack trace of the passed {@link Throwable}
* in the detailed description of the error.
* The throwable and the short description are mandatory to present to the user the
* message.
*
* @param shortDescription A short description of the message
* @param t The not
* This happens when the user presses the OK button but it might happen
* when the abnormal situation has been fixed and therefore jlog has
* no reason to ask for the attention of the user.
* One example could be that of an automatic reconnection.
*/
public void removeMessage() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setVisible(false);
}
});
}
public JButton getAckButton() {
return ackBtn;
}
/**
* Add a listener to be notified when the user presses the ack button.
*
* @param listener The listener to add to the list of listeners;
* the listener is not added if it is already in the list
*/
public void addAckListener(MessageWidgetListener listener) {
if (listener==null) {
throw new IllegalArgumentException("The listener can't be null");
}
if (ackListeners==null) {
Vectornull
or empty.
* @return true
if the detailed description is not empty i.e. the description
* scroll panel is visible
*/
public boolean showMessage(final MessageType messageType, final String shortDescription, final String description) {
if (messageType==null) {
throw new IllegalArgumentException("The type can't be null");
}
if (shortDescription==null || shortDescription.isEmpty()) {
throw new IllegalArgumentException("Invalid message descritpion");
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
shortDescriptionLbl.setText(shortDescription);
iconLbl.setIcon(messageType.icon);
setVisible(true);
if (description!=null && !description.isEmpty()) {
detailedDescritpionTA.setText(description);
detailedDescPnl.setVisible(true);
titleLbl.setText(""+messageType+"");
titleLbl.setVisible(true);
} else {
detailedDescritpionTA.setText("");
detailedDescPnl.setVisible(false);
titleLbl.setVisible(false);
}
}
});
return (description!=null && !description.isEmpty());
}
/**
* Show the glass pane and catches all the events until the user acknowledges the message
* by pressing the button.
* null
throwable to be displayed in the detailed text area.
* @return true
if the detailed description is not empty i.e. the description
* scroll panel is visible
*/
public boolean showMessage(String shortDescription, Throwable t) {
if (t==null) {
throw new IllegalArgumentException("The throwable can't be null");
}
StringWriter writer = new StringWriter();
PrintWriter printW = new PrintWriter(writer);
printW.flush();
t.printStackTrace(printW);
String desc=writer.getBuffer().toString();
printW.close();
return showMessage(MessageType.Error,shortDescription,desc);
}
/**
* Hide the error panel.
* true
if an element was removed as a result of this call
*/
public boolean removeAckListener(MessageWidgetListener listener) {
if (listener==null) {
throw new IllegalArgumentException("The listener can't be null");
}
if (ackListeners==null) {
return false;
}
return ackListeners.remove(listener);
}
/**
* Notify all the listeners that the user acknowledged the message
*/
private void notifyListeners() {
if (ackListeners==null) {
return;
}
Iterator