Я хочу добиться окраски синтаксиса внутри JEditorPane, который уже оснащен комплектом редактора Java Netbeans (класс org.netbeans.modules.editor.java.JavaKit). Я заметил, что когда JEditorPane вместо этого имеет набор редактора RTF, ключевые слова окрашены (см. этот вопрос и ответ https://stackoverflow.com/a/67025502/8315843). Дело в том, что в Netbeans есть интересный компонент, называемый представлением различий, который я хочу использовать, и это представление различий использует две JEditorPanes, которые поставляются с этим Javakit, который, похоже, не предлагает окраску синтаксиса.
В приведенном ниже примере кода я показываю 2 возможных пути выполнения:
- В наборе редактора RTF ключевое слово public окрашено в синий цвет.
- Как видите, с Netbeans Javakit это не сработало.
Что касается ввода, я использую очень минималистский класс public class Hello {}, который находится в переменной с именем text.
boolean useNetbeansJavakit = JOptionPane.showConfirmDialog(null, "Use Netbeans Javakit ?") == JOptionPane.YES_OPTION;
JFrame f = new JFrame("JAVA Syntax Coloring");
// Create the StyleContext, the document and the pane
StyleContext sc = new StyleContext();
final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
JEditorPane pane;
if (useNetbeansJavakit) {
pane = new JEditorPane();
pane.setEditorKit(CloneableEditorSupport.getEditorKit("text/x-java"));
} else {
pane = new JEditorPane("text/rtf", "");
}
System.out.println(pane.getEditorKit());
pane.setDocument(doc);
// Create and add the constant width style
final Style cwStyle = sc.addStyle("ConstantWidth", null);
StyleConstants.setFontFamily(cwStyle, "monospaced");
StyleConstants.setForeground(cwStyle, Color.blue);
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
// Add the text to the document
doc.insertString(0, text, null);
// Only color the word public for now in a hardcoded style
doc.setCharacterAttributes(0, 6, cwStyle, false);
} catch (BadLocationException e) {
}
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
System.exit(1);
}
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(pane));
f.setSize(400, 300);
f.setVisible(true);
}
public static final String text = "public class Hello {}";
Вот файл сборки Gradle:
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
implementation files("${System.properties['java.home']}/../lib/tools.jar")
implementation 'org.netbeans.modules:org-netbeans-modules-java-editor:RELEASE123'
implementation 'org.netbeans.modules:org-netbeans-modules-editor-mimelookup-impl:RELEASE123'
implementation 'org.apache.commons:commons-lang3:3.10'
}
Я работал над попыткой использовать подсветку синтаксиса на основе лексера, но я не знаю, как его использовать, я могу только догадываться, как его использовать, как показано ниже, но я просто не понимаю, как это просто не приходит изначально. В библиотеке netbeans, похоже, есть все, чтобы сделать некоторую окраску синтаксиса (см. класс org.netbeans.modules.editor.lib2.highlighting.SyntaxHighlighting, но я не могу найти объяснения, как его использовать). В приведенном ниже коде я разбиваю текст на идентификаторы и проверяю ключевые слова, а затем добавляю информацию о цвете для токенов ключевых слов.
JFrame f = new JFrame("JAVA Syntax Coloring");
// Create the StyleContext, the document and the pane
StyleContext sc = new StyleContext();
final DefaultStyledDocument doc = new DefaultStyledDocument(sc);
JEditorPane pane = new JEditorPane();
pane.setEditorKit(CloneableEditorSupport.getEditorKit("text/x-java"));
System.out.println(pane.getEditorKit());
pane.setDocument(doc);
LexerBasedHighlightLayer lexerBasedHighlightLayer = (LexerBasedHighlightLayer) doc.getProperty(SemanticHighlighter.class);
HashMap<Token, Coloring> colorings = new HashMap<>(lexerBasedHighlightLayer.getColorings());
Language<JavaTokenId> java = JavaTokenId.language();
TokenHierarchy<String> th = TokenHierarchy.create(text, java);
TokenSequence<JavaTokenId> ts = th.tokenSequence(java);
while (ts.moveNext()) {
Token<JavaTokenId> token = ts.token();
String tokenText = token.text().toString();
if (tokenText.matches(
"(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)")) {
ColoringAttributes colorAttr = EnumUtils.getEnum(ColoringAttributes.class, tokenText.toUpperCase());
if (colorAttr != null) {
Coloring coloring = ColoringAttributes.add(ColoringAttributes.empty(), colorAttr);
colorings.put(token, coloring);
}
}
}
lexerBasedHighlightLayer.setColorings(colorings, colorings.keySet(), null);
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
// Add the text to the document
doc.insertString(0, text, null);
} catch (BadLocationException e) {
}
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
System.exit(1);
}
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(pane));
f.setSize(400, 300);
f.setVisible(true);
}
public static final String text = "public class Hello {}";
Информация о цвете настраивается в файлах XML в файле jar org-netbeans-modules-java-editor-RELEASE123.jar. Чтобы настроить собственные цвета, я скопировал каталог org/netbeans/modules/java/editor/resources из jar-файла в свою рабочую область по адресу src/main/resources/org/netbeans/modules/java/editor/resources.
Внутри файла src/main/resources/org/netbeans/modules/java/editor/resources/fontsColors.xml я добавил атрибут foreColor=blue в mod-public, чтобы попытаться выделить ключевое слово public в blue:
<fontcolor name="mod-public" foreColor="blue" />
Я также изменил файл fontsColors-highlighting.xml в том же каталоге, и теперь он выглядит так:
<fontscolors>
<fontcolor name="remove-surround-code-delete" foreColor="ffB4B4B4" bgColor="ffF5F5F5"/>
<fontcolor name="remove-surround-code-remain" bgColor="ffCCFFCC"/>
<fontcolor name="mod-public" foreColor="blue" />
</fontscolors>
Что мне здесь не хватает?