/* HTMLPane.java
*
* Created April 7, 2009
*
* This file is a part of Shoddy Battle.
* Copyright (C) 2009 Catherine Fitzpatrick and Benjamin Gwin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, visit the Free Software Foundation, Inc.
* online at http://gnu.org.
*/
package shoddybattleclient.utils;
import java.awt.Color;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.DefaultCaret;
import javax.swing.text.html.HTMLDocument;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import shoddybattleclient.LobbyWindow;
import shoddybattleclient.Preference;
/**
*
* @author ben
*/
public class HTMLPane extends JTextPane {
private static final int MAXIMUM_LINES = 500;
private int m_lines = 0;
//This being true means to use the user's settings
private boolean m_timestamps = true;
public HTMLPane() {
super();
setContentType("text/html");
setEditable(false);
setBackground(Color.WHITE);
setOpaque(true);
HTMLEditorKit kit = new HTMLEditorKit();
StyleSheet css = new StyleSheet();
css.importStyleSheet(HTMLPane.class.getResource("/shoddybattleclient/resources/main.css"));
kit.setStyleSheet(css);
setEditorKit(kit);
DefaultCaret caret = (DefaultCaret)getCaret();
caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE);
this.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
LobbyWindow.viewWebPage(e.getURL());
}
}
});
}
public void setTimeStampsEnabled(boolean enabled) {
m_timestamps = enabled;
}
/**
* Encode HTML entities.
* Copied from www.owasp.org.
*/
public static String htmlEntityEncode(String s) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9')) {
buf.append(c);
} else {
buf.append("" + (int)c + ";");
}
}
return buf.toString();
}
public void addMessage(String user, String message) {
addMessage(user, message, true);
}
public void addMessage(String user, String message, boolean encode) {
if (message == null) return;
if (encode) {
message = htmlEntityEncode(message);
}
StringBuffer buffer = new StringBuffer();
if (m_timestamps && Preference.timeStampsEnabled()) {
try {
Date d = new Date();
String format = Preference.getTimeStampFormat();
format = htmlEntityEncode(format);
SimpleDateFormat f = new SimpleDateFormat(format);
buffer.append("<font class='timestamp'>");
buffer.append(f.format(d));
buffer.append("</font>");
} catch (Exception e) {
}
}
if (user != null) {
buffer.append(user);
buffer.append(": ");
}
buffer.append(message);
String msg = new String(buffer);
msg = msg.replaceAll(" ", " ")
.replaceAll("\\b([^ ]*://[^ ]+)",
"<a href=\"$1\">$1</a>");
HTMLDocument doc = (HTMLDocument)getDocument();
HTMLEditorKit kit = (HTMLEditorKit)getEditorKit();
try {
kit.insertHTML(doc, doc.getLength(), msg, 1, 0, null);
if (++m_lines > MAXIMUM_LINES) {
int position = 0;
int index;
while (true) {
index = doc.getText(position, doc.getLength()).indexOf("\n");
if (index != 0) {
position += index;
break;
} else {
position += 1;
}
}
doc.remove(0, position);
}
//doc.dump(new java.io.PrintStream(new java.io.FileOutputStream("out.txt")));
} catch (Exception e) {
}
//scroll only if we are already at the bottom
JScrollBar vbar = ((JScrollPane)this.getParent().getParent()).getVerticalScrollBar();
if ((vbar.getValue() + vbar.getVisibleAmount()) == vbar.getMaximum()) {
this.setCaretPosition(doc.getLength());
}
}
private void clear() {
setText("");
m_lines = 0;
}
public static void main(String[] args) {
JFrame frame = new JFrame("test htmlpane");
frame.setSize(500, 300);
frame.setLayout(new java.awt.GridLayout(1, 1));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final HTMLPane pane = new HTMLPane();
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(pane);
frame.add(scrollPane);
pane.addMessage("Ben", "I am a polymath");
pane.addMessage("Catherine", "I agree wholeheartedly");
pane.addMessage("Catherine", "check out http://cathyisnotapolymath.com");
pane.addMessage(null, "<b>=========================</b>", false);
pane.addMessage(null, "<b>Begin turn #1</b>", false);
pane.addMessage(null, "<b>=========================</b>", false);
pane.addMessage("Ben", "<hr>'s are ugly");
frame.setVisible(true);
/*new Thread(new Runnable() {
public void run() {
for (int i = 0; ; i++) {
pane.addMessage("spammer", String.valueOf(i));
synchronized (this) {
try {
wait(100);
} catch (InterruptedException ex) {
}
}
}
}
}).run();*/
}
}