package org.oddjob.monitor.view;
/**
* Display messages. Based on an example from Log4j.
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import java.util.Observer;
import java.util.StringTokenizer;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.BadLocationException;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.oddjob.logging.LogLevel;
import org.oddjob.monitor.model.LogAction;
import org.oddjob.monitor.model.LogEventProcessor;
public class LogTextPanel extends JPanel
implements Observer, LogEventProcessor {
private static final long serialVersionUID = 2009071400L;
private static final int MAX_DOC_LENGTH = 100000;
private JTextPane textPane;
private JCheckBox cbxTail;
private StyledDocument doc;
private Hashtable<LogLevel, MutableAttributeSet> fontAttributes;
public LogTextPanel(Observable model) {
model.addObserver(this);
constructComponents();
createDefaultFontAttributes();
}
private void constructComponents() {
// setup the panel's additional components...
this.setLayout(new BorderLayout());
cbxTail = new JCheckBox();
cbxTail.setSelected(true);
cbxTail.setText("Tail log events");
cbxTail.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (cbxTail.isSelected()) {
textPane.setCaretPosition(doc.getLength());
}
}
});
JPanel bottomPanel = new JPanel();
bottomPanel.add(cbxTail, null);
textPane = new JTextPane() {
private static final long serialVersionUID = 2010022700L;
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
};
textPane.setEditable(false);
textPane.setText("");
doc = textPane.getStyledDocument();
JScrollPane scroll = new JScrollPane();
scroll.setViewportView(textPane);
scroll.getViewport().setBackground(Color.white );
this.add(bottomPanel, BorderLayout.SOUTH);
this.add(scroll, BorderLayout.CENTER);
}
public void setTextBackground(Color color) {
textPane.setBackground(color);
}
public void setTextBackground(String v) {
textPane.setBackground(parseColor(v));
}
private void createDefaultFontAttributes() {
LogLevel[] prio = new LogLevel[] {
LogLevel.FATAL,
LogLevel.ERROR,
LogLevel.WARN,
LogLevel.INFO,
LogLevel.DEBUG,
LogLevel.TRACE };
fontAttributes = new Hashtable<LogLevel, MutableAttributeSet>();
for (int i = 0; i < prio.length; i++) {
MutableAttributeSet att = new SimpleAttributeSet();
fontAttributes.put(prio[i], att);
//StyleConstants.setFontSize(att,11);
}
setTextColor(LogLevel.FATAL, Color.red);
setTextColor(LogLevel.ERROR, Color.magenta.darker());
setTextColor(LogLevel.WARN, Color.orange.darker());
setTextColor(LogLevel.INFO, Color.blue);
setTextColor(LogLevel.DEBUG, Color.black);
setTextColor(LogLevel.TRACE, Color.darkGray);
setTextFontName("Lucida Console");
}
private Color parseColor(String v) {
StringTokenizer st = new StringTokenizer(v, ",");
int val[] = { 255, 255, 255, 255 };
int i = 0;
while (st.hasMoreTokens()) {
val[i] = Integer.parseInt(st.nextToken());
i++;
}
return new Color(val[0], val[1], val[2], val[3]);
}
void setTextColor(LogLevel l, String v) {
StyleConstants.setForeground((MutableAttributeSet) fontAttributes
.get(l), parseColor(v));
}
void setTextColor(LogLevel l, Color c) {
StyleConstants.setForeground((MutableAttributeSet) fontAttributes
.get(l), c);
}
void setTextFontSize(int size) {
Enumeration<?> e = fontAttributes.elements();
while (e.hasMoreElements()) {
StyleConstants.setFontSize((MutableAttributeSet) e.nextElement(),
size);
}
return;
}
void setTextFontName(String name) {
Enumeration<?> e = fontAttributes.elements();
while (e.hasMoreElements()) {
StyleConstants.setFontFamily((MutableAttributeSet) e.nextElement(),
name);
}
return;
}
public void onClear() {
try {
doc.remove(0, doc.getLength());
} catch (BadLocationException e) {
e.printStackTrace();
}
}
public void onUnavailable() {
textPane.setText(("No log available."));
}
public void onEvent(final String text, final LogLevel level) {
try {
doc.insertString(doc.getLength(), text,
(MutableAttributeSet) fontAttributes
.get(level));
int overflow = doc.getLength() - MAX_DOC_LENGTH;
if (overflow > 0) {
doc.remove(0, overflow);
// this will work when we move to 1.5 and can use
// DefaultCaret.NEVER_UPDATE but at the moment the caret
// does it's own thing on remove and we can't change it.
if (!cbxTail.isSelected()) {
int position = textPane.getCaretPosition();
if (position - overflow < 0) {
position = 0;
}
textPane.setCaretPosition(position);
}
}
if (cbxTail.isSelected()) {
textPane.setCaretPosition(doc.getLength());
}
} catch (BadLocationException e) {
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void update(Observable o, Object arg) {
LogAction a = (LogAction) arg;
a.accept(this);
}
}