JAVA Swing JTextPane拡張、テキストハイライトを実現
12519 ワード
JTextPane 拡張改造により、マルチキーワードの異なる色のハイライト、日付のハイライトを実現 および コメントハイライト、行数制御
import java.awt.Color;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.apache.commons.lang3.time.DateUtils;
import com.google.common.collect.ImmutableMap;
import freemarker.template.utility.DateUtil;
import psl.dg.com.StringUtils;
/**
* JTextPane, JTextPane (java 、 、 )
*
* @author yangze
* @since 2019-09-15
*
*/
public class MyJTextPane extends JTextPane implements DocumentListener {
private Set keywords;
private Map key2Color = new HashMap();
private Style keywordStyle;
private Style normalStyle;
private Style datetimeStyle;
private Style classNameStyle;
private int holdLineNum;
public MyJTextPane() {
super();
this.getDocument().addDocumentListener(this);
//
/*keywordStyle = ((StyledDocument) getDocument()).addStyle(
"Keyword_Style", null);
StyleConstants.setForeground(keywordStyle, Color.BLUE);*/
normalStyle = ((StyledDocument) getDocument()).addStyle(
"Keyword_Style", null);
StyleConstants.setForeground(normalStyle, Color.BLACK);
datetimeStyle = ((StyledDocument) getDocument()).addStyle(
"Keyword_Style", null);
StyleConstants.setForeground(datetimeStyle, Color.BLUE);
key2Color = ImmutableMap.of(" CSV ", Color.GREEN, " FTL ", Color.GREEN," ",Color.RED);
//
keywords = key2Color.keySet();
holdLineNum = -1;
}
/**
*
*
* @param attr
* @param replace
*/
public void setTextAttributes(AttributeSet attr, boolean replace) {
int p0 = 0;
int p1 = this.getText().length();
if (p0 != p1) {
StyledDocument doc = getStyledDocument();
doc.setCharacterAttributes(p0, p1 - p0, attr, replace);
} else {
MutableAttributeSet inputAttributes = getInputAttributes();
if (replace) {
inputAttributes.removeAttributes(inputAttributes);
}
inputAttributes.addAttributes(attr);
}
}
/**
*
*/
public void setSingleLineNoteCharacterAttributes() {
String text = this.getText();
int startPointer = 0;
int endPointer = 0;
if ((startPointer = text.indexOf("//")) == -1) {
return;
}
while ((endPointer = text.substring(startPointer).indexOf("
")) != -1) {
endPointer = startPointer + endPointer;
if (startPointer >= endPointer) {
break;
}
int hangshu = text.substring(0, endPointer).split("\
").length;
System.out.println("hangshu:" + hangshu);
SwingUtilities
.invokeLater(new ColouringWord(this, startPointer - hangshu
+ 1, endPointer - hangshu, new Color(63, 217, 95)));
startPointer = text.substring(endPointer + 1).indexOf("//");
startPointer = startPointer + endPointer + 1;
}
}
/**
*
*/
public void setMultiLineNoteCharacterAttributes() {
String text = this.getText();
int startPointer = 0;
int endPointer = 0;
if ((startPointer = text.indexOf("/*")) == -1) {
return;
}
while ((endPointer = text.substring(startPointer).indexOf("*/")) != -1) {
endPointer = startPointer + endPointer;
if (startPointer >= endPointer) {
break;
}
int hangshu = text.substring(0, endPointer).split("\
").length;
int kuaju = text.substring(startPointer, endPointer).split("\
").length;
SwingUtilities.invokeLater(new ColouringWord(this, startPointer
- hangshu + kuaju, endPointer + 3 - hangshu, new Color(63,
217, 95)));
startPointer = text.substring(endPointer + 1).indexOf("/*");
startPointer = startPointer + endPointer + 1;
}
}
/**
*
* @param styledDocument
* @param pos
* @param len
* @throws BadLocationException
*/
public void myColouring(StyledDocument styledDocument, int pos, int len)
throws BadLocationException {
int start = indexOfWordStart(styledDocument, pos);
int end = indexOfWordEnd(styledDocument, pos + len);
char ch;
while (start < end) {
ch = getCharAt(styledDocument, start);
if (Character.isLetter(ch) || ch == '_') {//
start = myColouringWord(styledDocument, start);
}
else if(Character.isDigit(ch)){
start = myColouringDateTime(styledDocument, start);
}else {
SwingUtilities.invokeLater(new ColouringTask(styledDocument,
start, 1, normalStyle));
++start;
}
}
}
/**
*
*
* @param doc
* @param pos
* @return
* @throws BadLocationException
*/
public int myColouringWord(StyledDocument doc, int pos)
throws BadLocationException {
int wordEnd = indexOfWordEnd(doc, pos);
String word = doc.getText(pos, wordEnd - pos);
if (keywords.contains(word)) {
keywordStyle = ((StyledDocument) getDocument()).addStyle(
"Keyword_Style", null);
StyleConstants.setForeground(keywordStyle, key2Color.get(word));
SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd
- pos, keywordStyle));
} else {
SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd
- pos, normalStyle));
}
return wordEnd;
}
public int myColouringDateTime(StyledDocument doc, int pos)
throws BadLocationException {
int endPos = doc.getLength();
if(endPos - pos < 19) return pos+1;
else {
int wordEnd = pos + 19;
String word = doc.getText(pos, wordEnd - pos);
if(psl.dg.com.DateUtils.isDatetime(word)) {
SwingUtilities.invokeLater(new ColouringTask(doc, pos, wordEnd
- pos, datetimeStyle));
return wordEnd;
}
return pos+1;
}
}
/**
* pos .
*
* @param doc
* @param pos
* @return
* @throws BadLocationException
*/
public char getCharAt(Document doc, int pos) throws BadLocationException {
return doc.getText(pos, 1).charAt(0);
}
/**
* pos , .
*
* @param doc
* @param pos
* @return
* @throws BadLocationException
*/
public int indexOfWordStart(Document doc, int pos)
throws BadLocationException {
// pos .
for (; pos > 0 && isWordCharacter(doc, pos - 1); --pos)
;
return pos;
}
public void setHoldLineNum(int num) {
this.holdLineNum = num;
this.setText(checkLine(this.getText()));
}
public String checkLine(String oldStr) {
if(holdLineNum > 0) {
String[] strArr = oldStr.split("
");
if(holdLineNum < strArr.length ) {
String newStr = "";
for(int i = strArr.length - holdLineNum ; i < strArr.length; ++i) {
newStr += strArr[i] + "
";
}
newStr = newStr.substring(0,newStr.length() - 1);
return newStr;
}
else {
return oldStr;
}
}else if(holdLineNum == 0) {
return "";
}else{
return oldStr;
}
}
public void appendLine(String text) {
String str = this.getText();
if(StringUtils.isBlank(str)) {
this.setText(checkLine(text));
}
else{
this.setText(checkLine(str + "
" + text));
}
}
/**
* pos , .
*
* @param doc
* @param pos
* @return
* @throws BadLocationException
*/
public int indexOfWordEnd(Document doc, int pos)
throws BadLocationException {
// pos .
for (; isWordCharacter(doc, pos); ++pos)
;
return pos;
}
/**
* , , , true.
*
* @param doc
* @param pos
* @return
* @throws BadLocationException
*/
public boolean isWordCharacter(Document doc, int pos)
throws BadLocationException {
char ch = getCharAt(doc, pos);
if (Character.isLetter(ch) || Character.isDigit(ch) || ch == '_' ) {
return true;
}
return false;
}
@Override
//
public void changedUpdate(DocumentEvent e) {
}
@Override
//
public void insertUpdate(DocumentEvent e) {
try {
myColouring((StyledDocument) e.getDocument(), e.getOffset(),
e.getLength());
// noteFinder.ColorNote(this.getText());//
setSingleLineNoteCharacterAttributes();
setMultiLineNoteCharacterAttributes();
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
@Override
//
public void removeUpdate(DocumentEvent e) {
try {
// ,
myColouring((StyledDocument) e.getDocument(), e.getOffset(), 0);
// noteFinder.ColorNote(this.getText());//
setSingleLineNoteCharacterAttributes();
setMultiLineNoteCharacterAttributes();
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
/**
*
*/
private class ColouringTask implements Runnable {
private StyledDocument doc;
private Style style;
private int pos;
private int len;
public ColouringTask(StyledDocument doc, int pos, int len, Style style) {
this.doc = doc;
this.pos = pos;
this.len = len;
this.style = style;
}
public void run() {
try {
//
doc.setCharacterAttributes(pos, len, style, false);
} catch (Exception e) {
}
}
}
}
/**
*
*
*
*
*/
class ColouringWord implements Runnable {
private int startPointer;
private int endPointer;
private Color color;
private JTextPane jTextPane;
public ColouringWord(JTextPane jTextPane, int pos, int len, Color color) {
this.jTextPane = jTextPane;
this.startPointer = pos;
this.endPointer = len;
this.color = color;
}
@Override
public void run() {
SimpleAttributeSet attributeSet = new SimpleAttributeSet();
StyleConstants.setForeground(attributeSet, color);
boolean replace = false;
int p0 = startPointer;
int p1 = endPointer;
if (p0 != p1) {
StyledDocument doc = jTextPane.getStyledDocument();
doc.setCharacterAttributes(p0, p1 - p0, attributeSet, replace);
} else {
MutableAttributeSet inputAttributes = jTextPane
.getInputAttributes();
if (replace) {
inputAttributes.removeAttributes(inputAttributes);
}
inputAttributes.addAttributes(attributeSet);
}
}
}