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); } } }