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