Eclipse color theme importer, initial implementation

This commit is contained in:
Rustam Vishnyakov
2016-04-07 18:53:34 +03:00
parent 69a0eb8efc
commit a2a4c7f433
10 changed files with 761 additions and 29 deletions
@@ -32,13 +32,21 @@ public class EmptyColorScheme extends DefaultColorsScheme {
public final static String NAME = "Empty";
public final static EmptyColorScheme INSTANCE = new EmptyColorScheme();
private final static TextAttributes EMPTY_TEXT = new TextAttributes(Color.BLACK, Color.white, null, EffectType.BOXED, Font.PLAIN);
private final static TextAttributes EMPTY_TEXT = new TextAttributes(Color.BLACK, Color.white, null, EffectType.BOXED, Font.PLAIN);
private final static TextAttributes DEFAULT_ATTRS = new TextAttributes(Color.GRAY, null, null, EffectType.BOXED, Font.PLAIN);
private EmptyColorScheme() {
myAttributesMap.put(HighlighterColors.TEXT, EMPTY_TEXT);
initFonts();
}
@Nullable
@Override
public TextAttributes getAttributes(TextAttributesKey key) {
TextAttributes attributes = super.getAttributes(key);
return attributes == null ? DEFAULT_ATTRS : attributes;
}
@Nullable
@Override
protected TextAttributes getKeyDefaults(@NotNull TextAttributesKey key) {
@@ -19,9 +19,6 @@ import com.intellij.application.options.ImportSourceChooserDialog;
import com.intellij.application.options.SaveSchemeDialog;
import com.intellij.application.options.SchemesToImportPopup;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.options.*;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.DialogWrapper;
@@ -44,7 +41,8 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@@ -154,7 +152,8 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper {
@Nullable
private CodeStyleScheme importExternalCodeStyle(final SchemeImporter<CodeStyleScheme> importer) throws SchemeImportException {
final VirtualFile selectedFile = selectImportSource(importer.getSourceExtensions());
final VirtualFile selectedFile = SchemeImportUtil
.selectImportSource(importer.getSourceExtensions(), myContentPane, CodeStyleSchemesUIConfiguration.Util.getRecentImportFile());
if (selectedFile != null) {
CodeStyleSchemesUIConfiguration.Util.setRecentImportFile(selectedFile);
final SchemeCreator schemeCreator = new SchemeCreator();
@@ -169,27 +168,6 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper {
return null;
}
@Nullable
private VirtualFile selectImportSource(final String[] sourceExtensions) {
final Set<String> extensions = new HashSet<String>(Arrays.asList(sourceExtensions));
FileChooserDialog fileChooser = FileChooserFactory.getInstance()
.createFileChooser(new FileChooserDescriptor(true, false, false, false, false, false) {
@Override
public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
return file.isDirectory() || extensions.contains(file.getExtension());
}
@Override
public boolean isFileSelectable(VirtualFile file) {
return !file.isDirectory() && extensions.contains(file.getExtension());
}
}, null, myContentPane);
final VirtualFile[] virtualFiles = fileChooser.choose(null, CodeStyleSchemesUIConfiguration.Util.getRecentImportFile());
if (virtualFiles.length != 1) return null;
virtualFiles[0].refresh(false, false);
return virtualFiles[0];
}
private void updateActions() {
// there is a possibility that nothing will be selected in a table. So we just need to corresponding disable actions
final CodeStyleScheme selectedScheme = getSelectedInTableScheme();
@@ -57,8 +57,6 @@ import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.diff.FilesTooBigForDiffException;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
@@ -137,6 +135,23 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
private MyColorScheme getScheme(String name) {
return mySchemes.get(name);
}
@NotNull
public String getUniqueName(@NotNull String preferredName) {
String name;
if (mySchemes.containsKey(preferredName)) {
for (int i = 1; ; i++) {
name = preferredName + " (" + i + ")";
if (!mySchemes.containsKey(name)) {
break;
}
}
}
else {
name = preferredName;
}
return name;
}
public EditorColorsScheme getSelectedScheme() {
return mySelectedScheme;
@@ -16,11 +16,20 @@
package com.intellij.application.options.colors;
import com.intellij.application.options.ImportSourceChooserDialog;
import com.intellij.application.options.SaveSchemeDialog;
import com.intellij.application.options.SkipSelfSearchComponent;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl;
import com.intellij.openapi.editor.colors.impl.EmptyColorScheme;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.options.SchemeImportException;
import com.intellij.openapi.options.SchemeImportUtil;
import com.intellij.openapi.options.SchemeImporter;
import com.intellij.openapi.options.SchemeImporterEP;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.EventDispatcher;
import com.intellij.util.containers.ContainerUtil;
@@ -39,6 +48,7 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent {
private JComboBox mySchemeComboBox;
private JButton myDeleteButton;
private JButton myImportButton;
private JLabel myHintLabel;
private final EventDispatcher<ColorAndFontSettingsListener> myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class);
@@ -114,6 +124,16 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent {
panel.add(myDeleteButton,
new GridBagConstraints(gridx++, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new JBInsets(0, 0, 5, 5), 0,
0));
myImportButton = new JButton("Import...");
myImportButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
chooseAndImport();
}
});
panel.add(myImportButton,
new GridBagConstraints(gridx++, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new JBInsets(0, 0, 5, 5), 0,
0));
myHintLabel = new JLabel(ApplicationBundle.message("hint.readonly.scheme.cannot.be.modified"));
myHintLabel.setEnabled(false);
panel.add(myHintLabel,
@@ -196,4 +216,38 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent {
public void addListener(ColorAndFontSettingsListener listener) {
myDispatcher.addListener(listener);
}
private void chooseAndImport() {
ImportSourceChooserDialog<EditorColorsScheme> importSourceChooserDialog =
new ImportSourceChooserDialog<EditorColorsScheme>(this, EditorColorsScheme.class);
if (importSourceChooserDialog.showAndGet()) {
final String selectedImporterName = importSourceChooserDialog.getSelectedSourceName();
if (selectedImporterName != null) {
final SchemeImporter<EditorColorsScheme> importer = SchemeImporterEP.getImporter(selectedImporterName, EditorColorsScheme.class);
if (importer != null) {
VirtualFile importSource = SchemeImportUtil.selectImportSource(importer.getSourceExtensions(), this, null);
if (importSource != null) {
try {
EditorColorsScheme imported =
importer.importScheme(DefaultProjectFactory.getInstance().getDefaultProject(), importSource, myOptions.getSelectedScheme(),
name -> {
String newName = myOptions.getUniqueName(name);
EditorColorsScheme newScheme = new EditorColorsSchemeImpl(EmptyColorScheme.INSTANCE);
newScheme.setName(newName);
return newScheme;
});
if (imported != null) {
myOptions.addImportedScheme(imported);
}
}
catch (SchemeImportException e) {
e.printStackTrace();
}
}
}
}
}
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.options;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDialog;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class SchemeImportUtil {
@Nullable
public static VirtualFile selectImportSource(@NotNull final String[] sourceExtensions,
@NotNull Component parent,
@Nullable VirtualFile preselect) {
final Set<String> extensions = new HashSet<String>(Arrays.asList(sourceExtensions));
FileChooserDialog fileChooser = FileChooserFactory.getInstance()
.createFileChooser(new FileChooserDescriptor(true, false, false, false, false, false) {
@Override
public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
return file.isDirectory() || extensions.contains(file.getExtension());
}
@Override
public boolean isFileSelectable(VirtualFile file) {
return !file.isDirectory() && extensions.contains(file.getExtension());
}
}, null, parent);
final VirtualFile[] preselectFiles;
if (preselect != null) {
preselectFiles = new VirtualFile[1];
preselectFiles[0] = preselect;
}
else {
preselectFiles = new VirtualFile[0];
}
final VirtualFile[] virtualFiles = fileChooser.choose(null, preselectFiles);
//CodeStyleSchemesUIConfiguration.Util.getRecentImportFile());
if (virtualFiles.length != 1) return null;
virtualFiles[0].refresh(false, false);
return virtualFiles[0];
}
}
@@ -29,6 +29,10 @@
name="Eclipse XML Profile"
implementationClass="org.jetbrains.idea.eclipse.importer.EclipseCodeStyleSchemeImporter"
schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme"/>
<schemeImporter
name="Eclipse Color Theme (XML)"
implementationClass="org.jetbrains.idea.eclipse.importer.colors.EclipseColorSchemeImporter"
schemeClass="com.intellij.openapi.editor.colors.EditorColorsScheme"/>
<moduleService serviceImplementation="org.jetbrains.idea.eclipse.config.EclipseModuleManagerImpl"/>
</extensions>
@@ -0,0 +1,193 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.eclipse.importer.colors;
import com.intellij.execution.process.ConsoleHighlighter;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.diff.DiffColors;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.SchemeFactory;
import com.intellij.openapi.options.SchemeImportException;
import com.intellij.openapi.options.SchemeImporter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.ColorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.IOException;
import java.io.InputStream;
@SuppressWarnings("UseJBColor")
public class EclipseColorSchemeImporter implements SchemeImporter<EditorColorsScheme>, EclipseColorThemeElements {
private final static String[] ECLIPSE_THEME_EXTENSIONS = {"xml"};
private final static TextAttributesKey[] ATTRIBUTES_TO_COPY = {
HighlighterColors.BAD_CHARACTER,
CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES,
CodeInsightColors.ERRORS_ATTRIBUTES,
CodeInsightColors.WARNINGS_ATTRIBUTES,
CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING,
CodeInsightColors.DUPLICATE_FROM_SERVER,
CodeInsightColors.WEAK_WARNING_ATTRIBUTES,
CodeInsightColors.INFORMATION_ATTRIBUTES,
CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES,
CodeInsightColors.DEPRECATED_ATTRIBUTES,
CodeInsightColors.LINE_FULL_COVERAGE,
CodeInsightColors.LINE_PARTIAL_COVERAGE,
CodeInsightColors.LINE_NONE_COVERAGE,
ConsoleViewContentType.NORMAL_OUTPUT_KEY,
ConsoleViewContentType.ERROR_OUTPUT_KEY,
ConsoleViewContentType.USER_INPUT_KEY,
ConsoleViewContentType.SYSTEM_OUTPUT_KEY,
ConsoleViewContentType.LOG_ERROR_OUTPUT_KEY,
ConsoleViewContentType.LOG_WARNING_OUTPUT_KEY,
ConsoleViewContentType.LOG_EXPIRED_ENTRY,
ConsoleHighlighter.BLACK,
ConsoleHighlighter.RED,
ConsoleHighlighter.GREEN,
ConsoleHighlighter.YELLOW,
ConsoleHighlighter.BLUE,
ConsoleHighlighter.MAGENTA,
ConsoleHighlighter.CYAN,
ConsoleHighlighter.GRAY,
ConsoleHighlighter.DARKGRAY,
ConsoleHighlighter.RED_BRIGHT,
ConsoleHighlighter.GREEN_BRIGHT,
ConsoleHighlighter.YELLOW_BRIGHT,
ConsoleHighlighter.BLUE_BRIGHT,
ConsoleHighlighter.MAGENTA_BRIGHT,
ConsoleHighlighter.CYAN_BRIGHT,
ConsoleHighlighter.WHITE,
DiffColors.DIFF_ABSENT,
DiffColors.DIFF_CONFLICT,
DiffColors.DIFF_DELETED,
DiffColors.DIFF_INSERTED,
DiffColors.DIFF_MODIFIED,
DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE
};
//
// These attributes are referenced only symbolically since they are located outside this module's dependencies.
//
private final static String[] EXTERNAL_ATTRIBUTES = {
"BREAKPOINT_ATTRIBUTES",
"EXECUTIONPOINT_ATTRIBUTES",
"NOT_TOP_FRAME_ATTRIBUTES",
"DEBUGGER_INLINED_VALUES",
"DEBUGGER_INLINED_VALUES_MODIFIED",
"DEBUGGER_INLINED_VALUES_EXECUTION_LINE"
};
@NotNull
@Override
public String[] getSourceExtensions() {
return ECLIPSE_THEME_EXTENSIONS;
}
@Nullable
@Override
public EditorColorsScheme importScheme(@NotNull Project project,
@NotNull VirtualFile selectedFile,
@NotNull EditorColorsScheme currentScheme,
@NotNull SchemeFactory<EditorColorsScheme> schemeFactory) throws SchemeImportException {
String themeName = readSchemeName(selectedFile);
if (themeName != null) {
EditorColorsScheme colorsScheme = schemeFactory.createNewScheme(themeName);
readFromStream(selectedFile, new EclipseThemeOptionHandler(colorsScheme));
setupMissingColors(colorsScheme);
return colorsScheme;
}
return null;
}
private static String readSchemeName(@NotNull VirtualFile selectedFile) throws SchemeImportException {
return readFromStream(selectedFile, null);
}
private static String readFromStream(@NotNull final VirtualFile file,
@Nullable final EclipseThemeReader.OptionHandler optionHandler)
throws SchemeImportException {
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
EclipseThemeReader themeReader = new EclipseThemeReader(optionHandler);
themeReader.readSettings(inputStream);
return themeReader.getThemeName();
} catch (IOException e) {
throw new SchemeImportException(e);
}
finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
//
}
}
}
}
@Nullable
@Override
public String getAdditionalImportInfo(@NotNull EditorColorsScheme scheme) {
return null;
}
private static void setupMissingColors(@NotNull EditorColorsScheme scheme) {
Color background= scheme.getDefaultBackground();
String defaultSchemeName = ColorUtil.isDark(background) ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME;
EditorColorsScheme baseScheme = DefaultColorSchemesManager.getInstance().getScheme(defaultSchemeName);
assert baseScheme != null : "Can not find default scheme '" + defaultSchemeName + "'!";
for (TextAttributesKey attributesKey : ATTRIBUTES_TO_COPY) {
copyAttributes(baseScheme, scheme, attributesKey);
}
for (String keyName : EXTERNAL_ATTRIBUTES) {
TextAttributesKey key = TextAttributesKey.createTextAttributesKey(keyName);
copyAttributes(baseScheme, scheme, key);
}
Color lightForeground = ColorUtil.mix(background, scheme.getDefaultForeground(), 0.5);
scheme.setColor(EditorColors.WHITESPACES_COLOR, lightForeground);
scheme.setColor(EditorColors.INDENT_GUIDE_COLOR, lightForeground);
scheme.setColor(EditorColors.SOFT_WRAP_SIGN_COLOR, lightForeground);
TextAttributes matchedBrace = new TextAttributes();
matchedBrace.setEffectType(EffectType.BOXED);
matchedBrace.setEffectColor(lightForeground);
scheme.setAttributes(CodeInsightColors.MATCHED_BRACE_ATTRIBUTES, matchedBrace);
TextAttributes unmatchedBrace = matchedBrace.clone();
unmatchedBrace.setEffectColor(ColorUtil.mix(background, Color.RED, 0.5));
}
private static void copyAttributes(@NotNull EditorColorsScheme source, @NotNull EditorColorsScheme target, @NotNull TextAttributesKey key) {
target.setAttributes(key, source.getAttributes(key));
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.eclipse.importer.colors;
public interface EclipseColorThemeElements {
String BACKGROUND_SUFFIX = "background";
String COLOR_THEME_TAG = "colorTheme";
String SEARCH_RESULT_TAG = "searchResultIndication";
String FILTER_SEARCH_RESULT_TAG = "filteredSearchResultIndication";
String OCCURENCE_TAG = "occurrenceIndication";
String WRITE_OCCURENCE_TAG = "writeOccurrenceIndication";
String FIND_SCOPE_TAG = "findScope";
String DELETION_INDICATION_TAG = "deletionIndication";
String SOURCE_HOVER_BACKGROUND_TAG = "sourceHoverBackground";
String SINGLE_LINE_COMMENT_TAG = "singleLineComment";
String MULTI_LINE_COMMENT_TAG = "multiLineComment";
String COMMENT_TASK_TAG = "commentTaskTag";
String JAVADOC_TAG = "javadoc";
String JAVADOC_LINK_TAG = "javadocLink";
String JAVADOC_TAG_TAG = "javadocTag";
String JAVADOC_KEYWORD_TAG = "javadocKeyword";
String CLASS_TAG = "class";
String INTERFACE_TAG = "interface";
String METHOD_TAG = "method";
String METHOD_DECLARATION = "methodDeclaration";
String BRACKET = "bracket";
String NUMBER_TAG = "number";
String STRING_TAG = "string";
String OPERATOR_TAG = "operator";
String KEYWORD_TAG = "keyword";
String ANNOTATION_TAG = "annotation";
String STATIC_METHOD_TAG = "staticMethod";
String LOCAL_VARIABLE_TAG = "localVariable";
String LOCAL_VARIABLE_DECL_TAG = "localVariableDeclaration";
String FIELD_TAG = "field";
String STATIC_FIELD_TAG = "staticField";
String STATIC_FINAL_FIELD_TAG = "staticFinalField";
String DEPRECATED_MEMBER_TAG = "deprecatedMember";
String ENUM_TAG = "enum";
String INHERITED_METHOD_TAG = "inheritedMethod";
String ABSTRACT_METHOD_TAG = "abstractMethod";
String PARAMETER_VAR_TAG = "parameterVariable";
String TYPE_ARG_TAG = "typeArgument";
String TYPE_PARAM_TAG = "typeParameter";
String CONST_TAG = "constant";
String BACKGROUND_TAG = "background";
String CURR_LINE_TAG = "currentLine";
String FOREGROUND_TAG = "foreground";
String LINE_NUMBER_TAG = "lineNumber";
String SELECTION_BACKGROUND_TAG = "selectionBackground";
String SELECTION_FOREGROUND_TAG = "selectionForeground";
String NAME_ATTR = "name";
String COLOR_ATTR = "color";
String BOLD_ATTR = "bold";
String ITALIC_ATTR = "italic";
String UNDERLINE_ATTR = "underline";
String STRIKETHROUGH_ATTR = "strikethrough";
}
@@ -0,0 +1,166 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.eclipse.importer.colors;
import com.intellij.ide.highlighter.JavaHighlightingColors;
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.XmlHighlighterColors;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.colors.impl.AbstractColorsScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.Map;
@SuppressWarnings("UseJBColor")
public class EclipseThemeOptionHandler implements EclipseThemeReader.OptionHandler, EclipseColorThemeElements {
private EditorColorsScheme myColorsScheme;
private final static Map<String, TextAttributesKey> ECLIPSE_TO_IDEA_ATTR_MAP = new HashMap<>();
static {
ECLIPSE_TO_IDEA_ATTR_MAP.put(SINGLE_LINE_COMMENT_TAG, DefaultLanguageHighlighterColors.LINE_COMMENT);
ECLIPSE_TO_IDEA_ATTR_MAP.put(MULTI_LINE_COMMENT_TAG, DefaultLanguageHighlighterColors.BLOCK_COMMENT);
ECLIPSE_TO_IDEA_ATTR_MAP.put(JAVADOC_TAG, DefaultLanguageHighlighterColors.DOC_COMMENT);
ECLIPSE_TO_IDEA_ATTR_MAP.put(JAVADOC_TAG_TAG, DefaultLanguageHighlighterColors.DOC_COMMENT_MARKUP);
ECLIPSE_TO_IDEA_ATTR_MAP.put(JAVADOC_KEYWORD_TAG, DefaultLanguageHighlighterColors.DOC_COMMENT_TAG);
ECLIPSE_TO_IDEA_ATTR_MAP.put(CLASS_TAG, DefaultLanguageHighlighterColors.CLASS_NAME);
ECLIPSE_TO_IDEA_ATTR_MAP.put(INTERFACE_TAG, DefaultLanguageHighlighterColors.INTERFACE_NAME);
ECLIPSE_TO_IDEA_ATTR_MAP.put(METHOD_TAG, DefaultLanguageHighlighterColors.FUNCTION_CALL);
ECLIPSE_TO_IDEA_ATTR_MAP.put(METHOD_DECLARATION, DefaultLanguageHighlighterColors.FUNCTION_DECLARATION);
ECLIPSE_TO_IDEA_ATTR_MAP.put(NUMBER_TAG, DefaultLanguageHighlighterColors.NUMBER);
ECLIPSE_TO_IDEA_ATTR_MAP.put(ANNOTATION_TAG, DefaultLanguageHighlighterColors.METADATA);
ECLIPSE_TO_IDEA_ATTR_MAP.put(STATIC_METHOD_TAG, DefaultLanguageHighlighterColors.STATIC_METHOD);
ECLIPSE_TO_IDEA_ATTR_MAP.put(STATIC_FIELD_TAG, DefaultLanguageHighlighterColors.STATIC_FIELD);
ECLIPSE_TO_IDEA_ATTR_MAP.put(PARAMETER_VAR_TAG, DefaultLanguageHighlighterColors.PARAMETER);
ECLIPSE_TO_IDEA_ATTR_MAP.put(CONST_TAG, DefaultLanguageHighlighterColors.CONSTANT);
ECLIPSE_TO_IDEA_ATTR_MAP.put(COMMENT_TASK_TAG, CodeInsightColors.TODO_DEFAULT_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(TYPE_ARG_TAG, JavaHighlightingColors.TYPE_PARAMETER_NAME_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(ENUM_TAG, JavaHighlightingColors.ENUM_NAME_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(INHERITED_METHOD_TAG, JavaHighlightingColors.INHERITED_METHOD_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(ABSTRACT_METHOD_TAG, JavaHighlightingColors.ABSTRACT_METHOD_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(STATIC_FINAL_FIELD_TAG, JavaHighlightingColors.STATIC_FINAL_FIELD_ATTRIBUTES);
ECLIPSE_TO_IDEA_ATTR_MAP.put(DEPRECATED_MEMBER_TAG, CodeInsightColors.DEPRECATED_ATTRIBUTES);
}
public EclipseThemeOptionHandler(EditorColorsScheme colorsScheme) {
myColorsScheme = colorsScheme;
}
@Override
public void handleColorOption(@NotNull String name, @NotNull TextAttributes attributes) {
if (BACKGROUND_TAG.equals(name)) {
updateAttributes(HighlighterColors.TEXT, attributes);
myColorsScheme.setColor(EditorColors.GUTTER_BACKGROUND, attributes.getBackgroundColor());
}
else if (FOREGROUND_TAG.equals(name)) {
updateAttributes(HighlighterColors.TEXT, attributes);
updateAttributes(DefaultLanguageHighlighterColors.IDENTIFIER, attributes);
}
else if (CURR_LINE_TAG.equals(name)) {
myColorsScheme.setColor(EditorColors.CARET_ROW_COLOR, attributes.getForegroundColor());
}
else if (SELECTION_BACKGROUND_TAG.equals(name)) {
myColorsScheme.setColor(EditorColors.SELECTION_BACKGROUND_COLOR, attributes.getBackgroundColor());
}
else if (SELECTION_FOREGROUND_TAG.equals(name)) {
myColorsScheme.setColor(EditorColors.SELECTION_FOREGROUND_COLOR, attributes.getForegroundColor());
}
else if (BRACKET.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.BRACES, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.BRACKETS, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.PARENTHESES, attributes);
}
else if (OPERATOR_TAG.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.OPERATION_SIGN, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.COMMA, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.SEMICOLON, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.DOT, attributes);
}
else if (LINE_NUMBER_TAG.equals(name)) {
Color lineNumberColor = attributes.getForegroundColor();
myColorsScheme.setColor(EditorColors.LINE_NUMBERS_COLOR, lineNumberColor);
myColorsScheme.setColor(EditorColors.TEARLINE_COLOR, lineNumberColor);
myColorsScheme.setColor(EditorColors.RIGHT_MARGIN_COLOR, lineNumberColor);
myColorsScheme.setColor(EditorColors.CARET_COLOR, lineNumberColor);
}
else if(LOCAL_VARIABLE_TAG.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.LOCAL_VARIABLE, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.MARKUP_TAG, attributes);
}
else if(LOCAL_VARIABLE_DECL_TAG.equals(name)) {
myColorsScheme.setAttributes(XmlHighlighterColors.HTML_TAG_NAME, attributes);
myColorsScheme.setAttributes(XmlHighlighterColors.XML_TAG_NAME, attributes);
}
else if(FIELD_TAG.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.INSTANCE_FIELD, attributes);
myColorsScheme.setAttributes(XmlHighlighterColors.XML_ATTRIBUTE_NAME, attributes);
myColorsScheme.setAttributes(XmlHighlighterColors.HTML_ATTRIBUTE_NAME, attributes);
}
else if(OCCURENCE_TAG.equals(name)) {
myColorsScheme.setAttributes(EditorColors.IDENTIFIER_UNDER_CARET_ATTRIBUTES, toBackgroundAttributes(attributes));
}
else if (WRITE_OCCURENCE_TAG.equals(name)) {
myColorsScheme.setAttributes(EditorColors.WRITE_IDENTIFIER_UNDER_CARET_ATTRIBUTES, toBackgroundAttributes(attributes));
}
else if(SEARCH_RESULT_TAG.equals(name)) {
myColorsScheme.setAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES, toBackgroundAttributes(attributes));
}
else if(FILTER_SEARCH_RESULT_TAG.equals(name)) {
myColorsScheme.setAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES, toBackgroundAttributes(attributes));
}
else if (STRING_TAG.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.STRING, attributes);
TextAttributes validEscapeAttrs = attributes.clone();
validEscapeAttrs.setFontType(Font.BOLD);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE, validEscapeAttrs);
}
else if (KEYWORD_TAG.equals(name)) {
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.KEYWORD, attributes);
myColorsScheme.setAttributes(DefaultLanguageHighlighterColors.MARKUP_ENTITY, attributes);
}
else {
if (ECLIPSE_TO_IDEA_ATTR_MAP.containsKey(name)) {
myColorsScheme.setAttributes(ECLIPSE_TO_IDEA_ATTR_MAP.get(name), attributes);
}
}
}
private void updateAttributes(@NotNull TextAttributesKey key, @NotNull TextAttributes attributes) {
if (myColorsScheme instanceof AbstractColorsScheme) {
TextAttributes alreadyDefined = ((AbstractColorsScheme)myColorsScheme).getDirectlyDefinedAttributes(key);
if (alreadyDefined != null) {
if (attributes.getForegroundColor() != null) alreadyDefined.setForegroundColor(attributes.getForegroundColor());
if (attributes.getBackgroundColor() != null) alreadyDefined.setBackgroundColor(attributes.getBackgroundColor());
return;
}
}
myColorsScheme.setAttributes(key, attributes);
}
private static TextAttributes toBackgroundAttributes(@NotNull TextAttributes attributes) {
TextAttributes backgroundAttrs = attributes.clone();
backgroundAttrs.setBackgroundColor(attributes.getForegroundColor());
backgroundAttrs.setForegroundColor(null);
return backgroundAttrs;
}
}
@@ -0,0 +1,179 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.eclipse.importer.colors;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.options.SchemeImportException;
import com.intellij.util.containers.HashMap;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.awt.*;
import java.io.InputStream;
import java.util.Map;
@SuppressWarnings("UseJBColor")
public class EclipseThemeReader extends DefaultHandler implements EclipseColorThemeElements {
private @Nullable OptionHandler myOptionHandler;
private @Nullable String myThemeName;
private final static Map<String,Integer> ECLIPSE_DEFAULT_FONT_STYLES = new HashMap<>();
static {
ECLIPSE_DEFAULT_FONT_STYLES.put(KEYWORD_TAG, Font.BOLD);
}
public EclipseThemeReader(@Nullable OptionHandler handler) {
myOptionHandler = handler;
}
protected void readSettings(InputStream input) throws SchemeImportException {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(false);
SAXParser parser;
try {
parser = spf.newSAXParser();
parser.parse(input, this);
}
catch (Exception e) {
if (e.getCause() instanceof NotAnEclipseThemeException) {
throw new SchemeImportException("The input file is not a valid Eclipse theme.");
}
else {
throw new SchemeImportException(e);
}
}
}
private static class NotAnEclipseThemeException extends Exception {
public NotAnEclipseThemeException(String message) {
super(message);
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if (COLOR_THEME_TAG.equals(qName)) {
myThemeName = attributes.getValue(NAME_ATTR);
if (myThemeName == null) {
throw new SAXException(new NotAnEclipseThemeException("'name' attribute of 'colorTheme' is missing."));
}
}
else {
if (myThemeName != null) {
if (myOptionHandler != null) {
myOptionHandler.handleColorOption(qName, readTextAttributes(qName, attributes, isBackground(qName)));
}
}
else {
throw new SAXException(new NotAnEclipseThemeException("'colorTheme' element is missing."));
}
}
}
public interface OptionHandler {
void handleColorOption(@NotNull String name, @NotNull TextAttributes textAttribute);
}
private static TextAttributes readTextAttributes(@NotNull String tag, Attributes attributes, boolean isBackground) throws SAXException {
TextAttributes textAttributes = new TextAttributes();
Color color = getColor(attributes);
if (isBackground) {
textAttributes.setBackgroundColor(color);
}
else {
textAttributes.setForegroundColor(color);
}
textAttributes.setFontType(getFontStyle(tag, attributes));
EffectType effectType = getEffectType(attributes);
if (effectType != null) {
textAttributes.setEffectType(effectType);
textAttributes.setEffectColor(textAttributes.getForegroundColor());
}
return textAttributes;
}
private static boolean isBackground(@NotNull String tagName) {
if (tagName.length() >= BACKGROUND_SUFFIX.length()) {
tagName = tagName.substring(tagName.length() - BACKGROUND_SUFFIX.length());
return tagName.equalsIgnoreCase(BACKGROUND_SUFFIX);
}
return false;
}
@Nullable
public String getThemeName() {
return myThemeName;
}
@Nullable
private static Color getColor(Attributes attributes) throws SAXException {
String colorString = attributes.getValue(COLOR_ATTR);
if (colorString != null && colorString.length() > 0) {
try {
int colorValue = Integer.decode(colorString);
return new Color(colorValue);
}
catch (NumberFormatException nfe) {
throw new SAXException("Invalid color value: '" + colorString + "'");
}
}
return null;
}
@JdkConstants.FontStyle
private static int getFontStyle(@NotNull String tag, @NotNull Attributes attributes) {
int fontStyle = getDefaultFontStyle(tag);
String boldValue = attributes.getValue(BOLD_ATTR);
if (boldValue != null) {
if (Boolean.parseBoolean(boldValue)) fontStyle |= Font.BOLD;
else fontStyle &= ~Font.BOLD;
}
String italicValue = attributes.getValue(ITALIC_ATTR);
if (italicValue != null) {
if (Boolean.parseBoolean(italicValue)) fontStyle |= Font.ITALIC;
else fontStyle &= ~Font.ITALIC;
}
return fontStyle;
}
@SuppressWarnings("MagicConstant")
@JdkConstants.FontStyle
private static int getDefaultFontStyle(@NotNull String tag) {
if (ECLIPSE_DEFAULT_FONT_STYLES.containsKey(tag)) return ECLIPSE_DEFAULT_FONT_STYLES.get(tag);
return Font.PLAIN;
}
@Nullable
private static EffectType getEffectType(@NotNull Attributes attributes) {
String strikeThrough = attributes.getValue(STRIKETHROUGH_ATTR);
if (strikeThrough != null && Boolean.parseBoolean(strikeThrough)) {
return EffectType.STRIKEOUT;
}
String underline = attributes.getValue(UNDERLINE_ATTR);
if (underline != null && Boolean.parseBoolean(underline)) {
return EffectType.LINE_UNDERSCORE;
}
return null;
}
}