package org.buzztroll.mud;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import java.util.*;
import java.text.*;
public class
TextDisplay
extends DisplayInterface
implements ComponentListener,
MouseMotionListener,
MouseListener,
AdjustmentListener
{
protected TextCanvas textPane;
protected DefaultStyledDocument doc;
protected StyleSheet sc;
protected JScrollPane scrollPane;
protected Font defaultFont = null;
protected Color backgroundColor = Color.black;
protected Point lastMousePosition = null;
private String ls = null;
private ConfigFrame configFrame;
public
TextDisplay(ConfigFrame configFrame)
{
this.configFrame = configFrame;
ls = System.getProperty("line.separator");
MutableAttributeSet attr;
attr = new SimpleAttributeSet();
StyleConstants.ColorConstants.setBackground(attr, backgroundColor);
StyleConstants.setBackground(attr, backgroundColor);
sc = new StyleSheet();
doc = new DefaultStyledDocument(sc);
this.setBackground(Color.black);
this.setLayout(new BorderLayout());
textPane = new TextCanvas(doc);
textPane.setCharacterAttributes(attr, true);
textPane.setOpaque(true);
textPane.setEditable(false);
textPane.setBackground(backgroundColor);
textPane.setForeground(backgroundColor);
this.setBackground(Color.black);
this.setOpaque(false);
this.addComponentListener(this);
textPane.addComponentListener(this);
scrollPane = new JScrollPane(textPane);
scrollPane.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBackground(Color.black);
scrollPane.setOpaque(false);
scrollPane.getVerticalScrollBar().addAdjustmentListener(this);
int fontSize = StyleConstants.FontConstants.getFontSize(attr);
String fontName = StyleConstants.FontConstants.getFontFamily(attr);
defaultFont = new Font(fontName, Font.PLAIN, fontSize);
this.add("Center", scrollPane);
textPane.addMouseMotionListener(this);
textPane.addMouseListener(this);
bottomOut();
}
public void
setBackgroundColor(Color color)
{
this.backgroundColor = color;
textPane.setBackground(backgroundColor);
textPane.setForeground(backgroundColor);
}
public void
addMouseListener(
MouseListener l)
{
super.addMouseListener(l);
textPane.addMouseListener(l);
}
public void
addMessage(
DisplayMessage dm)
{
String message;
Color color;
MutableAttributeSet attr;
int start;
String fontName;
int fontSize;
FontMetrics fm;
Font f;
message = dm.getString();
color = dm.getColor();
if(message == null || message.equals(""))
{
return;
}
start = doc.getLength();
attr = new SimpleAttributeSet();
StyleConstants.ColorConstants.setForeground(attr, color);
StyleConstants.ParagraphConstants.setLineSpacing(attr, 5.0f);
f = dm.getFont();
if(f == null)
{
f = defaultFont;
}
fontSize = f.getSize();
fontName = f.getFamily();
StyleConstants.FontConstants.setFontFamily(attr, fontName);
StyleConstants.FontConstants.setFontSize(attr, fontSize);
StyleConstants.FontConstants.setBold(attr, f.isBold());
StyleConstants.FontConstants.setItalic(attr, f.isItalic());
try
{
//textPane.repaint();
if (start == 0) {
doc.insertString(start, message, attr);
} else {
doc.insertString(start, ls + message, attr);
}
}
catch(BadLocationException e)
{
System.err.println(e);
// e.printStackTrace();
}
repaint();
}
public void
adjustmentValueChanged(
AdjustmentEvent e)
{
}
public void
paintComponent(
Graphics g)
{
super.paintComponent(g);
bottomOut();
}
public void
setFont(
Font f)
{
this.defaultFont = f;
}
public void clear() {
textPane.setText("");
}
public Font
getFont()
{
return this.defaultFont;
}
protected void
bottomOut()
{
JScrollBar jsb;
jsb = scrollPane.getVerticalScrollBar();
jsb.setValue(jsb.getMaximum());
}
public void
componentHidden(ComponentEvent e)
{
}
public void
componentMoved(ComponentEvent e)
{
}
public void
componentResized(ComponentEvent e)
{
bottomOut();
}
public void
componentShown(ComponentEvent e)
{
bottomOut();
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent event) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {
if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) == 0) {
checkLinkClick(e);
}
}
private void checkLinkClick(MouseEvent event) {
String url = getText(event.getPoint());
if (url == null || url.indexOf("://") == -1) {
return;
}
if (url.charAt(0) == '"' ||
url.charAt(0) == '\'') {
url = url.substring(1);
}
int len = url.length();
if (len > 0 && (url.charAt(len-1) == '"' ||
url.charAt(len-1) == '\'')) {
url = url.substring(0, len-1);
}
String cmdstr = this.configFrame.getUrlViewerCmd();
if (cmdstr == null || cmdstr.length() == 0) {
// FIXME: display error?
System.err.println("Url viewer cmd not defined");
return;
}
// on windows: rundll32 url.dll,FileProtocolHandler {0}
String cmd = MessageFormat.format(cmdstr, new Object [] {url});
try {
Process child = Runtime.getRuntime().exec(cmd);
} catch (Exception e) {
System.err.println("Error starting external viewer: " +
e.getMessage());
e.printStackTrace();
}
}
public String getText() {
return getText(lastMousePosition);
}
public String getText(Point p)
{
int pos = textPane.viewToModel(p);
try
{
if (Character.isWhitespace(doc.getText(pos, 1).charAt(0)))
{
return null;
}
}
catch (Exception ex)
{
return null;
}
// we should be over some text definitely now
Element elem = doc.getParagraphElement(pos);
int start = elem.getStartOffset();
int end = elem.getEndOffset();
int parOff = pos-start;
String line = null;
try {
line = doc.getText(start, end-start);
} catch (Exception ee) {
return null;
}
int i = parOff;
while( i < line.length() && !Character.isWhitespace(line.charAt(i)) ) {
i++;
}
end = i;
i = parOff;
while( i > 0 && line.charAt(i-1) != ' ') {
i--;
}
start = i;
return line.substring(start, end);
}
class
TextCanvas
extends JTextPane
{
public
TextCanvas(
StyledDocument doc)
{
super();
this.setDocument(doc);
this.setOpaque(true);
this.setBackground(backgroundColor);
}
}
// highlighting code
public void mouseMoved(MouseEvent event) {
lastMousePosition = event.getPoint();
int pos = textPane.viewToModel(lastMousePosition);
try {
if (Character.isWhitespace(doc.getText(pos, 1).charAt(0))) {
if (highlight != null) {
MutableAttributeSet attr = highlight.getAttribute();
StyleConstants.setUnderline(attr, false);
doc.setCharacterAttributes(highlight.getPosition(), highlight.getLength(), attr, false);
highlight = null;
}
return;
}
} catch (Exception ex) {
return;
}
// we should be over some text definitely now
if (highlight != null) {
if (highlight.isHighlighted(pos)) {
return;
} else {
MutableAttributeSet attr = highlight.getAttribute();
StyleConstants.setUnderline(attr, false);
doc.setCharacterAttributes(highlight.getPosition(), highlight.getLength(), attr, false);
highlight = null;
}
}
Element elem = doc.getParagraphElement(pos);
int start = elem.getStartOffset();
int end = elem.getEndOffset();
String line = null;
try {
line = doc.getText(start, end-start);
} catch (Exception ee) {
return;
}
int parOff = pos-start;
int i = parOff;
while( i < line.length() && !Character.isWhitespace(line.charAt(i)) ) {
i++;
}
end = i;
i = parOff;
while( i > 0 && line.charAt(i-1) != ' ') {
i--;
}
start = i;
line = line.substring(start, end);
// not an url
if (line.indexOf("://") == -1) {
return;
}
if (highlight == null) {
highlight = new Highlight();
}
MutableAttributeSet attr = new SimpleAttributeSet(elem.getAttributes());
highlight.setPosition(pos - (parOff -start));
highlight.setLength(end-start);
highlight.setAttribute(attr);
StyleConstants.setUnderline(attr, true);
doc.setCharacterAttributes(pos - (parOff -start), end-start, attr, false);
}
public void mouseDragged(MouseEvent event) {}
Highlight highlight;
class Highlight {
int pos;
int len;
MutableAttributeSet attr;
public void setPosition(int pos) {
this.pos = pos;
}
public void setLength(int len) {
this.len = len;
}
public int getLength() {
return this.len;
}
public int getPosition() {
return this.pos;
}
public void setAttribute(MutableAttributeSet attr) {
this.attr = attr;
}
public MutableAttributeSet getAttribute() {
return this.attr;
}
public boolean isHighlighted(int off) {
return (off > pos && off < pos + len);
}
}
}