Home > Software engineering >  Why custom styled document can't work with custom filter document?
Why custom styled document can't work with custom filter document?

Time:07-18

I am new to the java-swing library and currently I'm working on a text editor for a programming language. I have add the highlight key words future and it work fine.

I also need to add other futures such as auto indent, auto pair,... To do this I need to add my custom document filter:

((AbstractDocument) textPane.getDocument()).setDocumentFilter(new CustomDocumentFilter())

However, when I add the custom filter, the highlighter stops working. I don't know what's going on, but I think maybe the highlighter is using the default filter and when I add it, it overrides the default one. I also searched for "addDocumentFilter" but the framework does not offer such a method.

Here is the complete code:

public class CustomDocumentFilter extends DocumentFilter {

    public CustomDocumentFilter() {
       //...
    }
    //...
}

public class HighlightStyledDocument extends DefaultStyledDocument {
    private final Style defaultStyle;
    private final Style myStyle;

    public HighlightStyledDocument(StyleContext styleContext) {
        super(styleContext);

        this.defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
        this.myStyle = styleContext.addStyle("mystyle", null);
        StyleConstants.setForeground(myStyle, Color.BLUE);
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        super.insertString(offs, str, a);
        highlight();
    }

    @Override
    public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        highlight();
    }

    private synchronized void highlight() {
        SwingUtilities.invokeLater(() -> {
            try {
                String text = getText(0, getLength());
                setCharacterAttributes(0, text.length(), defaultStyle, true);
                for (Matcher m = KEYWORDS.matcher(text); m.find(); ) {
                    setCharacterAttributes(m.start(), m.end()-m.start(), myStyle, true);
                }
            } catch (BadLocationException ignored) {
            }
        });
    }


    public static final Pattern KEYWORDS = Pattern.compile(
            "(\\b)(void|int|if|else|while|switch|for|do|float)(\\b)",
            Pattern.CASE_INSENSITIVE);
}

public class Main extends JFrame {

    public Main() {
        JTextPane textPane = new JTextPane(new HighlightStyledDocument(new StyleContext()));
        add(textPane, BorderLayout.CENTER);
        setSize(new Dimension(200, 200));

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        
        //if I comment this line, the highlighter work fine !!!
        ((AbstractDocument) textPane.getDocument()).setDocumentFilter(new CustomDocumentFilter());
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Main main = new Main();
            main.setVisible(true);
        });
    }
}
    

I will be grateful if someone could help me.

CodePudding user response:

Based on @camickr's comment, here's the answer

public class CustomDocumentFilter extends DocumentFilter {

    public CustomDocumentFilter() {

    }
}

public class HighlightStyledDocument extends DefaultStyledDocument {
    private final Style defaultStyle;
    private final Style myStyle;

    public HighlightStyledDocument(StyleContext styleContext) {
        super(styleContext);

        this.defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
        this.myStyle = styleContext.addStyle("mystyle", null);
        StyleConstants.setForeground(myStyle, Color.BLUE);
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
        super.insertString(offs, str, a);
        highlight();
    }

    @Override
    public void remove(int offs, int len) throws BadLocationException {
        super.remove(offs, len);
        highlight();
    }

    @Override
    protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) {
        super.insertUpdate(chng, attr);
        highlight();
    }

    private void highlight() {
        try {
            String text = getText(0, getLength());
            setCharacterAttributes(0, text.length(), defaultStyle, true);
            for (Matcher m = KEYWORDS.matcher(text); m.find(); ) {
                setCharacterAttributes(m.start(), m.end()-m.start(), myStyle, true);
            }
        } catch (BadLocationException ignored) {
        }
    }

    public static final Pattern KEYWORDS = Pattern.compile(
            "(\\b)(void|int|if|else|while|switch|for|do|float)(\\b)",
            Pattern.CASE_INSENSITIVE);
}

public class Main extends JFrame {

    public Main() {
        JTextPane textPane = new JTextPane(new HighlightStyledDocument(new StyleContext()));
        add(textPane, BorderLayout.CENTER);
        setSize(new Dimension(200, 200));

        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);

        AbstractDocument doc;
        StyledDocument styledDoc = textPane.getStyledDocument();
        if (styledDoc instanceof AbstractDocument) {
            doc = (AbstractDocument)styledDoc;
            doc.setDocumentFilter(new CustomDocumentFilter());
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            Main main = new Main();
            main.setVisible(true);
        });
    }
}
  • Related