package aima.gui.swing.framework;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintStream;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
* Implements a simple text panel for message display.
*
* @author Ruediger Lunde
*/
public class MessageLoggerPanel extends JPanel implements MessageLogger {
private static final long serialVersionUID = 1L;
protected JTextArea textArea;
private boolean logLater;
public MessageLoggerPanel() {
setLayout(new BorderLayout());
textArea = new JTextArea();
textArea.setEditable(false);
// Use a fixed width font to help make the output easier to read.
textArea.setFont(new Font(Font.MONOSPACED, textArea.getFont()
.getStyle(), 14));
JScrollPane scrollPane = new JScrollPane(textArea);
add(scrollPane, BorderLayout.CENTER);
createPopupMenu();
}
/**
* Controls whether method <code>log</code> waits until the message is
* printed (value false) or does the work in background (value true).
* Waiting can slow down working threads significantly but the other option
* might cause deadlocks when log messages are printed before the frame was
* made visible under Java7.
*/
public void setLogLater(boolean b) {
logLater = b;
}
/** Removes the text from the text area. */
public void clear() {
textArea.setText("");
}
/** Prints a log message on the text area. */
public void log(final String message) {
if (EventQueue.isDispatchThread()) {
printMessage(message);
} else {
Runnable r = new Runnable() {
@Override
public void run() {
printMessage(message);
}
};
try {
if (logLater)
EventQueue.invokeLater(r);
else
EventQueue.invokeAndWait(r);
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void printMessage(String message) {
int start = textArea.getDocument().getLength();
textArea.append(message + "\n");
int end = textArea.getDocument().getLength();
textArea.setSelectionStart(start);
textArea.setSelectionEnd(end);
}
/**
* Provides a print stream which can be used to redirect standard output
* streams.
*/
public PrintStream getPrintStream() {
return new PrintStream(new TextAreaOutputStream());
}
/** Responsible for creating a popup menu for the panel. */
protected void createPopupMenu() {
JPopupMenu popup = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Clear");
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
clear();
}
});
popup.add(menuItem);
textArea.addMouseListener(new PopupShower(popup));
}
// ///////////////////////////////////////////////////////////////
// nested classes
/** Writes everything into the text area. */
private class TextAreaOutputStream extends java.io.OutputStream {
@Override
public void write(int b) throws java.io.IOException {
String s = new String(new char[] { (char) b });
textArea.append(s);
}
}
}