diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java index 4ba8a25730f3..2346253229fc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java @@ -21,6 +21,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.JavaHighlightInfoTypes; import com.intellij.lang.ASTNode; +import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.TextAttributesScheme; @@ -154,7 +155,9 @@ public class HighlightNamesUtil { } HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(varType).range(elementToHighlight); - return RainbowHighlighter.isRainbowEnabled() ? builder.createUnconditionally() : builder.create(); + return RainbowHighlighter.isRainbowEnabledWithInheritance(colorsScheme, JavaLanguage.INSTANCE) + ? builder.createUnconditionally() + : builder.create(); } @Nullable diff --git a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java index 0069c98c26b3..a6c706f4b8f7 100644 --- a/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java +++ b/java/java-impl/src/com/intellij/openapi/options/colors/pages/JavaColorSettingsPage.java @@ -16,8 +16,12 @@ package com.intellij.openapi.options.colors.pages; import com.intellij.application.options.colors.InspectionColorSettingsPage; +import com.intellij.codeHighlighting.RainbowHighlighter; import com.intellij.ide.highlighter.JavaFileHighlighter; import com.intellij.ide.highlighter.JavaHighlightingColors; +import com.intellij.lang.Language; +import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.StdFileTypes; @@ -25,18 +29,18 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.options.colors.AttributesDescriptor; import com.intellij.openapi.options.colors.ColorDescriptor; -import com.intellij.openapi.options.colors.ColorSettingsPage; +import com.intellij.openapi.options.colors.RainbowColorSettingsPage; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.codeStyle.DisplayPriority; import com.intellij.psi.codeStyle.DisplayPrioritySortable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.HashMap; import java.util.Map; -public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable { +public class JavaColorSettingsPage implements RainbowColorSettingsPage, InspectionColorSettingsPage, DisplayPrioritySortable { private static final AttributesDescriptor[] ourDescriptors = { new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.keyword"), JavaHighlightingColors.KEYWORD), new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.number"), JavaHighlightingColors.NUMBER), @@ -89,7 +93,7 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.annotation.attribute.name"), JavaHighlightingColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES) }; - @NonNls private static final Map ourTags = new HashMap<>(); + @NonNls private static final Map ourTags = RainbowHighlighter.createRainbowHLM(); static { ourTags.put("field", JavaHighlightingColors.INSTANCE_FIELD_ATTRIBUTES); ourTags.put("unusedField", CodeInsightColors.NOT_USED_ELEMENT_ATTRIBUTES); @@ -175,11 +179,22 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor " public static int staticField = 0;\n" + " public final int instanceFinalField = 0;\n" + "\n" + - " public SomeClass(AnInterface param, int[] reassignedParam) {\n" + + " /**\n" + + " * " + ApplicationBundle.message("rainbow.option.panel.display.name") + ":\n" + + " * " + RainbowHighlighter.generatePaletteExample() + "\n" + + " * @param param1\n" + + " * @param reassignedParam\n" + + " * @param param2\n" + + " * @param param3\n" + + " */\n" + + " public SomeClass(AnInterface param1, int[] reassignedParam,\n" + + " int param2\n" + + " int param3) {\n" + + " int reassignedValue = this.staticField + param2 + param3;\n" + + " long localVar1, localVar2, localVar3, localVar4;\n" + " int localVar = \"IntelliJ\"; // Error, incompatible types\n" + " System.out.println(anotherString + toString() + localVar);\n" + " long time = Date.parse(\"1.2.3\"); // Method is deprecated\n" + - " int reassignedValue = this.staticField; \n" + " reassignedValue ++; \n" + " field.run(); \n" + " new SomeClass() {\n" + @@ -190,7 +205,7 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor " reassignedParam = new ArrayList<String>().toArray(new int[0]);\n" + " }\n" + "}\n" + - "enum AnEnum { CONST1, CONST2 }\n"+ + "enum AnEnum { CONST1, CONST2 }\n" + "interface AnInterface {\n" + " int CONSTANT = 2;\n" + " void method();\n" + @@ -208,4 +223,19 @@ public class JavaColorSettingsPage implements ColorSettingsPage, InspectionColor public DisplayPriority getPriority() { return DisplayPriority.KEY_LANGUAGE_SETTINGS; } + + @Override + public boolean isRainbowType(TextAttributesKey type) { + return JavaHighlightingColors.LOCAL_VARIABLE_ATTRIBUTES.equals(type) + || JavaHighlightingColors.REASSIGNED_LOCAL_VARIABLE_ATTRIBUTES.equals(type) + || JavaHighlightingColors.PARAMETER_ATTRIBUTES.equals(type) + || JavaHighlightingColors.REASSIGNED_PARAMETER_ATTRIBUTES.equals(type) + || JavaHighlightingColors.DOC_COMMENT_TAG_VALUE.equals(type); + } + + @Nullable + @Override + public Language getLanguage() { + return JavaLanguage.INSTANCE; + } } diff --git a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java index f74e74b45e49..d73fdc6abfd6 100644 --- a/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java +++ b/platform/analysis-impl/src/com/intellij/codeHighlighting/RainbowHighlighter.java @@ -17,6 +17,7 @@ package com.intellij.codeHighlighting; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; +import com.intellij.lang.Language; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; @@ -24,17 +25,22 @@ import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.colors.TextAttributesScheme; import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.options.SchemeMetaInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.ui.ColorUtil; import com.intellij.ui.JBColor; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Properties; public class RainbowHighlighter { private static final JBColor[] RAINBOW_JB_COLORS_DEFAULT = { @@ -44,16 +50,25 @@ public class RainbowHighlighter { new JBColor(0x005910, 0xbe9970), new JBColor(0xbc5150, 0x9d527c), }; - private static final TextAttributesKey[] RAINBOW_COLOR_KEYS = new TextAttributesKey[RAINBOW_JB_COLORS_DEFAULT.length]; + public static final TextAttributesKey[] RAINBOW_COLOR_KEYS = new TextAttributesKey[RAINBOW_JB_COLORS_DEFAULT.length]; private static final int RAINBOW_COLORS_BETWEEN = 4; private static final String UNIT_TEST_COLORS = "#000001,#000002,#000003,#000004"; // Do not modify! + private static final String INHERITED = "inherited"; + static { for (int i = 0; i < RAINBOW_JB_COLORS_DEFAULT.length; ++i) { - JBColor jbColor = RAINBOW_JB_COLORS_DEFAULT[i]; - TextAttributes textAttributes = new TextAttributes(jbColor, null, null, null, Font.PLAIN); - RAINBOW_COLOR_KEYS[i] = TextAttributesKey.createTextAttributesKey("RAINBOW_COLOR" + i, textAttributes); + //noinspection deprecation + RAINBOW_COLOR_KEYS[i] = TextAttributesKey.createTextAttributesKey("RAINBOW_COLOR" + i, createRainbowAttribute(RAINBOW_JB_COLORS_DEFAULT[i])); } } + public final static String RAINBOW_TYPE = "rainbow"; + private final static String RAINBOW_TEMP_PREF = "RAINBOW_TEMP_"; + + @SuppressWarnings("deprecation") + public final static TextAttributesKey RAINBOW_ANCHOR = TextAttributesKey.createTextAttributesKey(RAINBOW_TYPE, new TextAttributes()); + @SuppressWarnings("deprecation") + public final static TextAttributesKey RAINBOW_GRADIENT_DEMO = TextAttributesKey.createTextAttributesKey("rainbow_demo", new TextAttributes()); + public final static Boolean DEFAULT_RAINBOW_ON = Boolean.FALSE; @NotNull private final TextAttributesScheme myColorsScheme; @NotNull private final Color[] myRainbowColors; @@ -65,11 +80,57 @@ public class RainbowHighlighter { public static final HighlightInfoType RAINBOW_ELEMENT = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION, DefaultLanguageHighlighterColors.CONSTANT); - public static boolean isRainbowEnabled() { - return Registry.is("editor.rainbow.identifiers", false); + @Nullable + @Contract("_, null -> !null") + public static Boolean isRainbowEnabled(@Nullable TextAttributesScheme colorsScheme, @Nullable Language language) { + if (colorsScheme instanceof SchemeMetaInfo) { + String value = ((SchemeMetaInfo)colorsScheme).getMetaProperties().getProperty(getKey(language), INHERITED); + if (String.valueOf(true).equals(value)) return Boolean.TRUE; + if (String.valueOf(false).equals(value)) return Boolean.FALSE; + return language == null ? DEFAULT_RAINBOW_ON : null; + } + return false; + } + + public static boolean isRainbowEnabledWithInheritance(@Nullable TextAttributesScheme colorsScheme, @Nullable Language language) { + Boolean rainbowEnabled = isRainbowEnabled(colorsScheme, language); + return rainbowEnabled != null ? rainbowEnabled : isRainbowEnabled(colorsScheme, null); + } + + public static void setRainbowEnabled(@NotNull SchemeMetaInfo colorsScheme, @Nullable Language language, @Nullable Boolean enabled) { + Properties properties = colorsScheme.getMetaProperties(); + String key = getKey(language); + if (enabled == null || (language == null && enabled == DEFAULT_RAINBOW_ON)) { + properties.remove(key); + } + else { + properties.setProperty(key, String.valueOf(enabled)); + } } @NotNull + private static String getKey(@Nullable Language language) { + return RAINBOW_TYPE + " " + (language == null ? "Default language" : language.getID()); + } + + @NotNull + public static String generatePaletteExample() { + int stopCount = RAINBOW_COLOR_KEYS.length; + StringBuilder sb = new StringBuilder(); + String tagRainbow = RAINBOW_GRADIENT_DEMO.getExternalName(); + for (int i = 0; i < RAINBOW_TEMP_KEYS.length; ++i) { + if (sb.length() != 0) { + sb.append(" "); + } + sb.append("<").append(tagRainbow).append(">"); + sb.append((i % stopCount == 0) ? "Stop#" + String.valueOf(i / stopCount + 1) : "T"); + sb.append(""); + } + return sb.toString(); + } + + @NotNull + @Contract(pure = true) private Color calculateForeground(int colorIndex) { return myRainbowColors[colorIndex]; } @@ -89,15 +150,37 @@ public class RainbowHighlighter { return registryColors.stream().map(s -> ColorUtil.fromHex(s.trim())).toArray(Color[]::new); } - List foregroundColors = ContainerUtil.map(RAINBOW_COLOR_KEYS, key -> colorsScheme.getAttributes(key).getForegroundColor()); - List colors = ColorGenerator.generateLinearColorSequence(foregroundColors, RAINBOW_COLORS_BETWEEN); + List stopColors = ContainerUtil.map(RAINBOW_COLOR_KEYS, key -> colorsScheme.getAttributes(key).getForegroundColor()); + List colors = ColorGenerator.generateLinearColorSequence(stopColors, RAINBOW_COLORS_BETWEEN); return colors.toArray(new Color[colors.size()]); } - public HighlightInfo getInfo(int colorIndex, @Nullable PsiElement id, @Nullable TextAttributesKey colorKey) { - if (id == null) { - return null; + @NotNull + public TextAttributesKey[] getRainbowTempKeys() { + TextAttributesKey[] keys = new TextAttributesKey[myRainbowColors.length]; + for (int i = 0; i < myRainbowColors.length; ++i) { + //noinspection deprecation + TextAttributesKey key = TextAttributesKey.createTextAttributesKey(RAINBOW_TEMP_PREF + i, new TextAttributes()); + key.getDefaultAttributes().setForegroundColor(myRainbowColors[i]); + keys[i] = key; } + return keys; + } + + public static boolean isRainbowTempKey(TextAttributesKey key) { + return key.getExternalName().startsWith(RAINBOW_TEMP_PREF); + } + + public HighlightInfo getInfo(int colorIndex, @Nullable PsiElement id, @Nullable TextAttributesKey colorKey) { + return id == null ? null : getInfoBuilder(colorIndex, colorKey).range(id).create(); + } + + public HighlightInfo getInfo(int colorIndex, int start, int end, @Nullable TextAttributesKey colorKey) { + return getInfoBuilder(colorIndex, colorKey).range(start, end).create(); + } + + @NotNull + protected HighlightInfo.Builder getInfoBuilder(int colorIndex, @Nullable TextAttributesKey colorKey) { if (colorKey == null) { colorKey = DefaultLanguageHighlighterColors.LOCAL_VARIABLE; } @@ -107,8 +190,25 @@ public class RainbowHighlighter { .fromFlyweight(myColorsScheme .getAttributes(colorKey) .getFlyweight() - .withForeground(calculateForeground(colorIndex)))) - .range(id) - .create(); + .withForeground(calculateForeground(colorIndex)))); + } + + private static final TextAttributesKey[] RAINBOW_TEMP_KEYS = new RainbowHighlighter(null).getRainbowTempKeys(); + + @NotNull + public static TextAttributes createRainbowAttribute(@Nullable Color color) { + TextAttributes ret = new TextAttributes(); + ret.setForegroundColor(color); + return ret; + } + + public static Map createRainbowHLM() { + Map hashMap = new HashMap<>(); + hashMap.put(RAINBOW_ANCHOR.getExternalName(), RAINBOW_ANCHOR); + hashMap.put(RAINBOW_GRADIENT_DEMO.getExternalName(), RAINBOW_GRADIENT_DEMO); + for (TextAttributesKey key : RAINBOW_TEMP_KEYS) { + hashMap.put(key.getExternalName(), key); + } + return hashMap; } } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/RainbowVisitor.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/RainbowVisitor.java index 3fede742b423..44ff60534678 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/RainbowVisitor.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/RainbowVisitor.java @@ -69,7 +69,7 @@ public abstract class RainbowVisitor implements HighlightVisitor { @NotNull final PsiElement rainbowElement, @NotNull final String name, @Nullable final TextAttributesKey colorKey) { - int colorIndex = UsedColors.getOrAddColorIndex((UserDataHolderEx)context, name, getHighlighter()); + int colorIndex = UsedColors.getOrAddColorIndex((UserDataHolderEx)context, name, getHighlighter().getColorsCount()); return getHighlighter().getInfo(colorIndex, rainbowElement, colorKey); } } diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/UsedColors.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/UsedColors.java index ca9248b6cbc7..a8a708d4c6b4 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/UsedColors.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/UsedColors.java @@ -15,16 +15,16 @@ */ package com.intellij.codeInsight.daemon; -import com.intellij.codeHighlighting.RainbowHighlighter; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderEx; import com.intellij.openapi.util.text.StringHash; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.concurrent.atomic.AtomicInteger; -class UsedColors { +public class UsedColors { private static final Key USED_COLOR = Key.create("USED_COLOR"); public static final AtomicInteger counter = new AtomicInteger(); @@ -39,10 +39,9 @@ class UsedColors { } } - static int getOrAddColorIndex(@NotNull final UserDataHolderEx context, - @NotNull final String name, - @NotNull RainbowHighlighter rainbowHighlighter) { - int colorsCount = rainbowHighlighter.getColorsCount(); + public static int getOrAddColorIndex(@NotNull final UserDataHolderEx context, + @NotNull final String name, + int colorsCount) { int colorIndex; while (true) { Object data = context.getUserData(USED_COLOR); @@ -101,6 +100,7 @@ class UsedColors { return Math.abs(StringHash.murmur(name, 0x55AA)) % colorsCount; } + @Contract(pure = true) private static int indexOfMin(@NotNull int[] values, int start, int end) { int min = Integer.MAX_VALUE; int minIndex = start; diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 8de1049f71ad..88bd2c079394 100644 --- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -142,7 +142,8 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP final List visitors = new ArrayList<>(highlightVisitors.length); List list = Arrays.asList(highlightVisitors); for (HighlightVisitor visitor : DumbService.getInstance(myProject).filterByDumbAwareness(list)) { - if (visitor instanceof RainbowVisitor && !RainbowHighlighter.isRainbowEnabled()) { + if (visitor instanceof RainbowVisitor + && !RainbowHighlighter.isRainbowEnabledWithInheritance(getColorsScheme(), psiFile.getLanguage())) { continue; } if (visitor.suitableForFile(psiFile)) { diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemeMetaInfo.java b/platform/core-api/src/com/intellij/openapi/options/SchemeMetaInfo.java new file mode 100644 index 000000000000..45389fbbddbc --- /dev/null +++ b/platform/core-api/src/com/intellij/openapi/options/SchemeMetaInfo.java @@ -0,0 +1,25 @@ +/* + * 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 org.jetbrains.annotations.NotNull; + +import java.util.Properties; + +public interface SchemeMetaInfo { + @NotNull + Properties getMetaProperties(); +} diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java index c5ca81b54f42..2aaf813d3a2d 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java @@ -18,6 +18,7 @@ package com.intellij.openapi.editor.colors; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.options.Scheme; +import com.intellij.openapi.options.SchemeMetaInfo; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -25,7 +26,7 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; -public interface EditorColorsScheme extends Cloneable, TextAttributesScheme, Scheme { +public interface EditorColorsScheme extends Cloneable, TextAttributesScheme, Scheme, SchemeMetaInfo { @NonNls String DEFAULT_SCHEME_NAME = "Default"; void setName(String name); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/EditorSchemeAttributeDescriptor.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptor.java similarity index 83% rename from platform/lang-impl/src/com/intellij/application/options/colors/EditorSchemeAttributeDescriptor.java rename to platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptor.java index fd5315664271..f174507a51c2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/EditorSchemeAttributeDescriptor.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -14,9 +14,7 @@ * limitations under the License. */ -package com.intellij.application.options.colors; - -import com.intellij.openapi.editor.colors.EditorColorsScheme; +package com.intellij.openapi.editor.colors; public interface EditorSchemeAttributeDescriptor { String getGroup(); diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptorWithPath.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptorWithPath.java new file mode 100644 index 000000000000..e5bc406340fd --- /dev/null +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorSchemeAttributeDescriptorWithPath.java @@ -0,0 +1,20 @@ +/* + * 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.editor.colors; + +public interface EditorSchemeAttributeDescriptorWithPath extends EditorSchemeAttributeDescriptor { + String NAME_SEPARATOR = "//"; +} diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index 1cb5c93d1f10..e3520f4bc8cf 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -830,4 +830,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { } public boolean isReadOnly() { return false; } + + @NotNull + @Override + public Properties getMetaProperties() { + return myMetaInfo; + } } diff --git a/platform/lang-api/src/com/intellij/openapi/options/colors/RainbowColorSettingsPage.java b/platform/lang-api/src/com/intellij/openapi/options/colors/RainbowColorSettingsPage.java new file mode 100644 index 000000000000..29f2bdb397c9 --- /dev/null +++ b/platform/lang-api/src/com/intellij/openapi/options/colors/RainbowColorSettingsPage.java @@ -0,0 +1,27 @@ +/* + * 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.colors; + +import com.intellij.lang.Language; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import org.jetbrains.annotations.Nullable; + +public interface RainbowColorSettingsPage extends ColorSettingsPage { + boolean isRainbowType(TextAttributesKey type); + + @Nullable + Language getLanguage(); +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java b/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java deleted file mode 100644 index 043aa0fd9bca..000000000000 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ClickNavigator.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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.application.options.colors; - -import com.intellij.application.options.colors.highlighting.HighlightData; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.HighlighterColors; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.colors.TextAttributesKey; -import com.intellij.openapi.editor.event.CaretAdapter; -import com.intellij.openapi.editor.event.CaretEvent; -import com.intellij.openapi.editor.event.CaretListener; -import com.intellij.openapi.editor.ex.EditorEx; -import com.intellij.openapi.editor.ex.util.EditorUtil; -import com.intellij.openapi.editor.highlighter.HighlighterIterator; -import com.intellij.openapi.fileTypes.SyntaxHighlighter; -import com.intellij.psi.tree.IElementType; -import com.intellij.ui.ScrollingUtil; -import com.intellij.util.ui.UIUtil; -import org.intellij.lang.annotations.JdkConstants; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionAdapter; - -public class ClickNavigator { - private final JList myOptionsList; - - public ClickNavigator(JList optionsList) { - myOptionsList = optionsList; - } - - public void addClickNavigatorToGeneralView(final Editor view) { - view.getContentComponent().addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - EditorUtil.setHandCursor(view); - } - }); - - CaretListener listener = new CaretAdapter() { - @Override - public void caretPositionChanged(CaretEvent e) { - setSelectedItem(HighlighterColors.TEXT.getExternalName(), true); - } - }; - view.getCaretModel().addCaretListener(listener); - } - - private boolean setSelectedItem(String type, boolean select) { - DefaultListModel model = (DefaultListModel)myOptionsList.getModel(); - - for (int i = 0; i < model.size(); i++) { - Object o = model.get(i); - if (o instanceof EditorSchemeAttributeDescriptor) { - if (type.equals(((EditorSchemeAttributeDescriptor)o).getType())) { - if (select) { - ScrollingUtil.selectItem(myOptionsList, i); - } - return true; - } - } - } - return false; - } - - private static boolean isWhiteSpace(int offset, CharSequence text) { - return offset <= 0 || offset >= text.length() || - text.charAt(offset) == ' ' || text.charAt(offset) == '\t' || - text.charAt(offset) == '\n' || text.charAt(offset) == '\r'; - } - - public static boolean highlightDataContainsOffset(HighlightData data, int offset) { - return offset >= data.getStartOffset() && offset <= data.getEndOffset(); - } - - public void addClickNavigator(final Editor view, - final SyntaxHighlighter highlighter, - final HighlightData[] data, - final boolean isBackgroundImportant) { - addMouseMotionListener(view, highlighter, data, isBackgroundImportant); - - CaretListener listener = new CaretAdapter() { - @Override - public void caretPositionChanged(CaretEvent e) { - navigate(view, true, e.getNewPosition(), highlighter, data, isBackgroundImportant); - } - }; - view.getCaretModel().addCaretListener(listener); - } - - private boolean selectItem(boolean select, HighlighterIterator itr, SyntaxHighlighter highlighter) { - - IElementType tokenType = itr.getTokenType(); - if (tokenType == null) return false; - String type = highlightingTypeFromTokenType(tokenType, highlighter); - return setSelectedItem(type, select); - } - - public static String highlightingTypeFromTokenType(IElementType tokenType, SyntaxHighlighter highlighter) { - TextAttributesKey[] highlights = highlighter.getTokenHighlights(tokenType); - String s = null; - for (int i = highlights.length - 1; i >= 0; i--) { - if (highlights[i] != HighlighterColors.TEXT) { - s = highlights[i].getExternalName(); - break; - } - } - return s == null ? HighlighterColors.TEXT.getExternalName() : s; - } - - private void addMouseMotionListener(final Editor view, - final SyntaxHighlighter highlighter, - final HighlightData[] data, final boolean isBackgroundImportant) { - view.getContentComponent().addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - LogicalPosition pos = view.xyToLogicalPosition(new Point(e.getX(), e.getY())); - navigate(view, false, pos, highlighter, data, isBackgroundImportant); - } - }); - } - - private void navigate(final Editor editor, boolean select, - LogicalPosition pos, - final SyntaxHighlighter highlighter, - final HighlightData[] data, final boolean isBackgroundImportant) { - int offset = editor.logicalPositionToOffset(pos); - - if (!isBackgroundImportant && editor.offsetToLogicalPosition(offset).column != pos.column) { - if (!select) { - setCursor(editor, Cursor.TEXT_CURSOR); - return; - } - } - - if (data != null) { - for (HighlightData highlightData : data) { - if (highlightDataContainsOffset(highlightData, editor.logicalPositionToOffset(pos))) { - if (!select) setCursor(editor, Cursor.HAND_CURSOR); - setSelectedItem(highlightData.getHighlightType(), select); - return; - } - } - } - - if (highlighter != null) { - HighlighterIterator itr = ((EditorEx)editor).getHighlighter().createIterator(offset); - boolean selection = selectItem(select, itr, highlighter); - if (!select && selection) { - setCursor(editor, Cursor.HAND_CURSOR); - } - else { - setCursor(editor, Cursor.TEXT_CURSOR); - } - } - } - - public static void setCursor(final Editor view, @JdkConstants.CursorType int type) { - final Cursor cursor = type == Cursor.TEXT_CURSOR && view instanceof EditorEx ? - UIUtil.getTextCursor(((EditorEx)view).getBackgroundColor()) : Cursor.getPredefinedCursor(type); - view.getContentComponent().setCursor(cursor); - } - -} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescription.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescription.java index 0e45a0af226e..db93b7363385 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescription.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescription.java @@ -17,6 +17,7 @@ package com.intellij.application.options.colors; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptorWithPath; import com.intellij.openapi.editor.colors.impl.AbstractColorsScheme; import com.intellij.openapi.editor.colors.impl.ReadOnlyColorsScheme; import com.intellij.openapi.editor.markup.EffectType; @@ -30,7 +31,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -public abstract class ColorAndFontDescription extends TextAttributes implements EditorSchemeAttributeDescriptor { +public abstract class ColorAndFontDescription extends TextAttributes implements EditorSchemeAttributeDescriptorWithPath { private final String myName; private final String myGroup; private final String myType; diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java index 152710c650e3..16c1462e75e6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java @@ -17,6 +17,8 @@ package com.intellij.application.options.colors; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptorWithPath; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.colors.AttributesDescriptor; @@ -29,12 +31,12 @@ import com.intellij.util.BitUtil; import com.intellij.util.EventDispatcher; import com.intellij.util.FontUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.HyperlinkEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -85,7 +87,7 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel super(new BorderLayout()); add(myPanel, BorderLayout.CENTER); - setBorder(BorderFactory.createEmptyBorder(4, 0, 4, 4)); + setBorder(JBUI.Borders.empty(4, 0, 4, 4)); myEffectsModel = new EffectsComboModel(ContainerUtil.newArrayList(myEffectsMap.keySet())); //noinspection unchecked myEffectsCombo.setModel(myEffectsModel); @@ -97,12 +99,16 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel } }); - ActionListener actionListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - onSettingsChanged(e); - } + ActionListener actionListener = e -> { + myErrorStripeColorChooser.setEnabled(myCbErrorStripe.isSelected()); + myForegroundChooser.setEnabled(myCbForeground.isSelected()); + myBackgroundChooser.setEnabled(myCbBackground.isSelected()); + myEffectsColorChooser.setEnabled(myCbEffects.isSelected()); + myEffectsCombo.setEnabled(myCbEffects.isSelected()); + + myDispatcher.getMulticaster().onSettingsChanged(e); }; + for (JBCheckBox c : new JBCheckBox[]{myCbBackground, myCbForeground, myCbEffects, myCbErrorStripe, myCbItalic, myCbBold, myInheritAttributesBox}) { c.addActionListener(actionListener); } @@ -110,14 +116,10 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel c.addActionListener(actionListener); } myEffectsCombo.addActionListener(actionListener); + Messages.configureMessagePaneUi(myInheritanceLabel, "", null); - myInheritanceLabel.addHyperlinkListener(new HyperlinkAdapter() { - @Override - protected void hyperlinkActivated(HyperlinkEvent e) { - onHyperLinkClicked(e); - } - }); - myInheritanceLabel.setBorder(BorderFactory.createEmptyBorder()); + myInheritanceLabel.addHyperlinkListener(e -> myDispatcher.getMulticaster().onHyperLinkClicked(e)); + myInheritanceLabel.setBorder(JBUI.Borders.empty(4, 0, 4, 4)); myLabelFont.setVisible(false); // hide for now as it doesn't look that good } @@ -127,20 +129,6 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel return this; } - private void onHyperLinkClicked(HyperlinkEvent e) { - myDispatcher.getMulticaster().onHyperLinkClicked(e); - } - - private void onSettingsChanged(ActionEvent e) { - myErrorStripeColorChooser.setEnabled(myCbErrorStripe.isSelected()); - myForegroundChooser.setEnabled(myCbForeground.isSelected()); - myBackgroundChooser.setEnabled(myCbBackground.isSelected()); - myEffectsColorChooser.setEnabled(myCbEffects.isSelected()); - myEffectsCombo.setEnabled(myCbEffects.isSelected()); - - myDispatcher.getMulticaster().onSettingsChanged(e); - } - public void resetDefault() { myLabelFont.setEnabled(false); myCbBold.setSelected(false); @@ -172,7 +160,10 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel colorPanel.setEnabled(isChecked); } - public void reset(@NotNull ColorAndFontDescription description) { + public void reset(@NotNull EditorSchemeAttributeDescriptor attrDescription) { + if (!(attrDescription instanceof ColorAndFontDescription)) return; + ColorAndFontDescription description = (ColorAndFontDescription)attrDescription; + if (description.isFontEnabled()) { myLabelFont.setEnabled(description.isEditable()); myCbBold.setEnabled(description.isEditable()); @@ -218,7 +209,7 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel Pair baseDescriptor = description.getBaseAttributeDescriptor(); if (baseDescriptor != null && baseDescriptor.second.getDisplayName() != null) { String attrName = baseDescriptor.second.getDisplayName(); - String attrLabel = attrName.replaceAll(ColorOptionsTree.NAME_SEPARATOR, FontUtil.rightArrow(UIUtil.getLabelFont())); + String attrLabel = attrName.replaceAll(EditorSchemeAttributeDescriptorWithPath.NAME_SEPARATOR, FontUtil.rightArrow(UIUtil.getLabelFont())); ColorSettingsPage settingsPage = baseDescriptor.first; String style = "
"; String tooltipText; @@ -263,7 +254,10 @@ public class ColorAndFontDescriptionPanel extends JPanel implements OptionsPanel myBackgroundChooser.setEditable(isEditEnabled); } - public void apply(@NotNull ColorAndFontDescription description, EditorColorsScheme scheme) { + public void apply(@NotNull EditorSchemeAttributeDescriptor attrDescription, EditorColorsScheme scheme) { + if (!(attrDescription instanceof ColorAndFontDescription)) return; + ColorAndFontDescription description = (ColorAndFontDescription)attrDescription; + description.setInherited(myInheritAttributesBox.isSelected()); if (description.isInherited()) { TextAttributes baseAttributes = description.getBaseAttributes(); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index 5bb1e1e11a40..5b29aa3186b4 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -27,18 +27,12 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.editor.colors.ColorKey; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.colors.impl.*; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SchemeManager; -import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.options.*; import com.intellij.openapi.options.colors.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; @@ -58,6 +52,7 @@ import com.intellij.psi.search.scope.packageSet.NamedScopesHolder; import com.intellij.psi.search.scope.packageSet.PackageSet; import com.intellij.ui.ColorUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.EventDispatcher; import com.intellij.util.ui.UIUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -77,6 +72,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract private Map mySchemes; private MyColorScheme mySelectedScheme; + public static final String FILE_STATUS_GROUP = ApplicationBundle.message("title.file.status"); public static final String SCOPES_GROUP = ApplicationBundle.message("title.scope.based"); @@ -94,6 +90,16 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract private boolean myDisposeCompleted = false; private final Disposable myDisposable = Disposer.newDisposable(); + private final EventDispatcher myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class); + + public void addListener(@NotNull ColorAndFontSettingsListener listener) { + myDispatcher.addListener(listener); + } + + public void stateChanged() { + myDispatcher.getMulticaster().settingsChanged(); + } + @Override public boolean isModified() { boolean listModified = isSchemeListModified(); @@ -106,7 +112,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract return listModified; } - private boolean isSchemeListModified(){ + private boolean isSchemeListModified() { if (mySomeSchemesDeleted) return true; if (!mySelectedScheme.getName().equals(EditorColorsManager.getInstance().getGlobalScheme().getName())) return true; @@ -508,7 +514,8 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract scheme.setDescriptors(descriptions.toArray(new EditorSchemeAttributeDescriptor[descriptions.size()])); } - private static void initPluggedDescriptions(@NotNull List descriptions, @NotNull MyColorScheme scheme) { + private static void initPluggedDescriptions(@NotNull List descriptions, + @NotNull MyColorScheme scheme) { ColorSettingsPage[] pages = ColorSettingsPages.getInstance().getRegisteredPages(); for (ColorSettingsPage page : pages) { initDescriptions(page, descriptions, scheme); @@ -523,8 +530,27 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract @NotNull MyColorScheme scheme) { String group = provider.getDisplayName(); List attributeDescriptors = ColorSettingsUtil.getAllAttributeDescriptors(provider); + //todo: single point configuration? + if (provider instanceof RainbowColorSettingsPage) { + descriptions.add(new RainbowAttributeDescriptor(((RainbowColorSettingsPage)provider).getLanguage(), + group, + ApplicationBundle.message("rainbow.option.panel.display.name"), + scheme, + scheme.myRainbowState)); + } for (AttributesDescriptor descriptor : attributeDescriptors) { addSchemedDescription(descriptions, descriptor.getDisplayName(), group, descriptor.getKey(), scheme, null, null); + // if (provider instanceof RainbowColorSettingsPage + // && ((RainbowColorSettingsPage)provider).isRainbowType(descriptor.getKey())) { + // //todo: joined sub-descriptor? + // descriptions.add(new RainbowAttributeDescriptor(group, + // descriptor.getDisplayName() + // + EditorSchemeAttributeDescriptorWithPath.NAME_SEPARATOR + // + ApplicationBundle.message("rainbow.option.panel.display.name"), + // scheme, + // scheme.getInitRainbowState(), + // scheme.getCurrentRainbowState())); + // } } ColorDescriptor[] colorDescriptors = provider.getColorDescriptors(); @@ -984,6 +1010,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract private EditorSchemeAttributeDescriptor[] myDescriptors; private String myName; private boolean myIsNew = false; + private RainbowColorsInSchemeState myRainbowState; private MyColorScheme(@NotNull EditorColorsScheme parentScheme) { super(parentScheme); @@ -996,6 +1023,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract setQuickDocFontSize(parentScheme.getQuickDocFontSize()); myName = parentScheme.getName(); + + //noinspection UseOfPropertiesAsHashtable + getMetaProperties().putAll(parentScheme.getMetaProperties()); + myRainbowState = new RainbowColorsInSchemeState(this, parentScheme); + initFonts(); } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java index 07507167eb6a..d9d216bcaf5c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java @@ -15,6 +15,8 @@ */ package com.intellij.application.options.colors; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptorWithPath; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.treeStructure.Tree; @@ -26,6 +28,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.tree.*; import java.util.*; +import static com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptorWithPath.NAME_SEPARATOR; + /** * @author Rustam Vishnyakov */ @@ -33,8 +37,6 @@ public class ColorOptionsTree extends Tree { private final String myCategoryName; private final DefaultTreeModel myTreeModel; - public final static String NAME_SEPARATOR = "//"; - private static final Comparator ATTR_COMPARATOR = (o1, o2) -> StringUtil.naturalCompare(o1.toString(), o2.toString()); @@ -78,9 +80,9 @@ public class ColorOptionsTree extends Tree { } @Nullable - public ColorAndFontDescription getSelectedDescriptor() { + public EditorSchemeAttributeDescriptor getSelectedDescriptor() { Object selectedValue = getSelectedValue(); - return selectedValue instanceof ColorAndFontDescription ? (ColorAndFontDescription)selectedValue : null; + return selectedValue instanceof EditorSchemeAttributeDescriptor ? (EditorSchemeAttributeDescriptor)selectedValue : null; } @Nullable @@ -138,7 +140,7 @@ public class ColorOptionsTree extends Tree { @Nullable private static List extractPath(@NotNull EditorSchemeAttributeDescriptor descriptor) { - if (descriptor instanceof ColorAndFontDescription) { + if (descriptor instanceof EditorSchemeAttributeDescriptorWithPath) { String name = descriptor.toString(); List path = new ArrayList<>(); int separatorStart = name.indexOf(NAME_SEPARATOR); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java index 0084ff8cc513..17654f1e3516 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java @@ -72,10 +72,6 @@ public class ColorSettingsUtil { return true; } - static boolean isSharedScheme(EditorColorsScheme selected) { - return false; - } - private static void addInspectionSeverityAttributes(List descriptors) { descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.unknown.symbol"), CodeInsightColors.WRONG_REFERENCES_ATTRIBUTES)); descriptors.add(new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.deprecated.symbol"), CodeInsightColors.DEPRECATED_ATTRIBUTES)); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/CustomizedSwitcherPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/CustomizedSwitcherPanel.java new file mode 100644 index 000000000000..0f18dfbfe188 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/CustomizedSwitcherPanel.java @@ -0,0 +1,154 @@ +/* + * 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.application.options.colors; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; +import com.intellij.openapi.options.colors.ColorSettingsPage; +import com.intellij.openapi.options.colors.RainbowColorSettingsPage; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; + +class CustomizedSwitcherPanel extends JPanel implements OptionsPanelImpl.ColorDescriptionPanel { + private ColorSettingsPage myPage; + + private PreviewPanel myPreviewPanel; + private ColorAndFontDescriptionPanel myColorAndFontPanel; + private RainbowDescriptionPanel myRainbowPanel; + + private OptionsPanelImpl.ColorDescriptionPanel myActive; + + public CustomizedSwitcherPanel(@Nullable PreviewPanel previewPanel, + @Nullable ColorSettingsPage page) { + super(); + myPage = page; + myPreviewPanel = previewPanel; + + myRainbowPanel = new RainbowDescriptionPanel(); + myColorAndFontPanel = new ColorAndFontDescriptionPanel(); + + Dimension sizeR = myRainbowPanel.getPreferredSize(); + Dimension sizeC = myColorAndFontPanel.getPreferredSize(); + Dimension preferredSize = new Dimension(); + preferredSize.setSize(Math.max(sizeR.getWidth(), sizeC.getWidth()), + Math.max(sizeR.getHeight(), sizeC.getHeight())); + setPreferredSize(preferredSize); + } + + @NotNull + @Override + public JComponent getPanel() { + return this; + } + + @Override + public void resetDefault() { + if (myActive != null) { + final PaintLocker locker = new PaintLocker(this); + try { + setPreferredSize(getSize());// froze [this] size + remove(myActive.getPanel()); + myActive = null; + } + finally { + locker.release(); + } + } + } + + @Override + public void reset(@NotNull EditorSchemeAttributeDescriptor descriptor) { + JComponent oldPanel = myActive == null ? null : myActive.getPanel(); + myActive = getPanelForDescriptor(descriptor); + JComponent newPanel = myActive == null ? null : myActive.getPanel(); + + if (oldPanel != newPanel) { + final PaintLocker locker = new PaintLocker(this); + try { + if (oldPanel != null) { + remove(oldPanel); + } + if (newPanel != null) { + setPreferredSize(null);// make [this] resizable + add(newPanel); + } + } + finally { + locker.release(); + } + } + if (myActive != null) { + myActive.reset(descriptor); + } + updatePreviewPanel(descriptor); + } + + protected OptionsPanelImpl.ColorDescriptionPanel getPanelForDescriptor(@NotNull EditorSchemeAttributeDescriptor descriptor) { + if (descriptor instanceof RainbowAttributeDescriptor) { + return myRainbowPanel; + } + else if (descriptor instanceof ColorAndFontDescription) { + return myColorAndFontPanel; + } + return null; + } + + + @Override + public void apply(@NotNull EditorSchemeAttributeDescriptor descriptor, EditorColorsScheme scheme) { + if (myActive != null) { + myActive.apply(descriptor, scheme); + updatePreviewPanel(descriptor); + } + } + + protected void updatePreviewPanel(@NotNull EditorSchemeAttributeDescriptor descriptor) { + if (!(myPreviewPanel instanceof SimpleEditorPreview && myPage instanceof RainbowColorSettingsPage)) return; + UIUtil.invokeAndWaitIfNeeded((Runnable)() -> ApplicationManager.getApplication().runWriteAction(() -> { + SimpleEditorPreview simpleEditorPreview = (SimpleEditorPreview)myPreviewPanel; + simpleEditorPreview.setupRainbow(descriptor.getScheme(), (RainbowColorSettingsPage)myPage); + simpleEditorPreview.updateView(); + })); + } + + @Override + public void addListener(@NotNull Listener listener) { + myRainbowPanel.addListener(listener); + myColorAndFontPanel.addListener(listener); + } + + private static class PaintLocker { + private Container myPaintHolder; + private boolean myPaintState; + + public PaintLocker(@NotNull JComponent component) { + myPaintHolder = component.getParent(); + myPaintState = myPaintHolder.getIgnoreRepaint(); + myPaintHolder.setIgnoreRepaint(true); + } + + public void release() { + myPaintHolder.validate(); + myPaintHolder.setIgnoreRepaint(myPaintState); + myPaintHolder.repaint(); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java index 35c49f0653eb..6e43fa0c7306 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java @@ -325,7 +325,7 @@ public class FontOptions extends JPanel implements OptionsPanel{ public boolean updateDescription(boolean modified) { EditorColorsScheme scheme = myOptions.getSelectedScheme(); - if (modified && (ColorAndFontOptions.isReadOnly(scheme) || ColorSettingsUtil.isSharedScheme(scheme))) { + if (modified && ColorAndFontOptions.isReadOnly(scheme)) { return false; } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java index 101ef5ec4797..7e84e0f37b04 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.options.colors.ColorSettingsPage; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.GuiUtils; import org.jetbrains.annotations.NotNull; @@ -100,10 +101,8 @@ public class NewColorAndFontPanel extends JPanel { optionsPanel.addListener(new ColorAndFontSettingsListener.Abstract() { @Override public void settingsChanged() { - if (schemesPanel.updateDescription(true)) { - optionsPanel.applyChangesToScheme(); - previewPanel.updateView(); - } + optionsPanel.applyChangesToScheme(); + previewPanel.updateView(); } @Override @@ -133,8 +132,9 @@ public class NewColorAndFontPanel extends JPanel { Collection optionList, ColorSettingsPage page) { final SchemesPanel schemesPanel = new SchemesPanel(options); - final OptionsPanel optionsPanel = new OptionsPanelImpl(options, schemesPanel, category); - + final OptionsPanel optionsPanel = new OptionsPanelImpl( + options, schemesPanel, category, + new CustomizedSwitcherPanel(previewPanel, page)); return new NewColorAndFontPanel(schemesPanel, optionsPanel, previewPanel, category, optionList, page); } @@ -148,13 +148,7 @@ public class NewColorAndFontPanel extends JPanel { if (myOptionList == null) { return myOptionsPanel.processListOptions(); } - else { - final HashSet result = new HashSet<>(); - for (String s : myOptionList) { - result.add(s); - } - return result; - } + return new HashSet<>(myOptionList); } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java b/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java index 5f4075c9abc5..0337f66d23dc 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java @@ -20,11 +20,11 @@ import com.intellij.ide.DataManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.util.ActionCallback; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.EventDispatcher; -import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -74,6 +74,7 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { @Override public void onSettingsChanged(ActionEvent e) { myDispatcher.getMulticaster().settingsChanged(); + myOptions.stateChanged(); } @Override @@ -99,6 +100,17 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { } }); + myOptions.addListener(new ColorAndFontSettingsListener.Abstract() { + @Override + public void settingsChanged() { + if (!mySchemesProvider.areSchemesLoaded()) return; + if (myOptionsTree.getSelectedValue() != null) { + // update options & preview after global state change + processListValueChanged(); + } + } + }); + myOptionsTree = new ColorOptionsTree(myCategoryName); myOptionsTree.addTreeSelectionListener(new TreeSelectionListener() { @@ -122,7 +134,9 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { private void processListValueChanged() { Object selectedValue = myOptionsTree.getSelectedValue(); - ColorAndFontDescription description = selectedValue instanceof ColorAndFontDescription ? (ColorAndFontDescription)selectedValue : null; + EditorSchemeAttributeDescriptor description = selectedValue instanceof EditorSchemeAttributeDescriptor + ? (EditorSchemeAttributeDescriptor)selectedValue + : null; if (description == null) { if (selectedValue == null) { String preselectedType = myProperties.getValue(SELECTED_COLOR_OPTION_PROPERTY); @@ -164,7 +178,7 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { @Override public void applyChangesToScheme() { - ColorAndFontDescription descriptor = myOptionsTree.getSelectedDescriptor(); + EditorSchemeAttributeDescriptor descriptor = myOptionsTree.getSelectedDescriptor(); if (descriptor != null) { myOptionsPanel.apply(descriptor, myOptions.getSelectedScheme()); } @@ -193,9 +207,9 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { void resetDefault(); - void reset(@NotNull ColorAndFontDescription description); + void reset(@NotNull EditorSchemeAttributeDescriptor description); - void apply(@NotNull ColorAndFontDescription descriptor, EditorColorsScheme scheme); + void apply(@NotNull EditorSchemeAttributeDescriptor descriptor, EditorColorsScheme scheme); void addListener(@NotNull Listener listener); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java new file mode 100644 index 000000000000..b4957eafd0b0 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowAttributeDescriptor.java @@ -0,0 +1,80 @@ +/* + * 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.application.options.colors; + +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.lang.Language; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptorWithPath; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +class RainbowAttributeDescriptor implements EditorSchemeAttributeDescriptorWithPath { + private final String myGroup; + private final String myDisplayName; + private final EditorColorsScheme myScheme; + private final Language myLanguage; + private final RainbowColorsInSchemeState myRainbowColorsInSchemaState; + + public RainbowAttributeDescriptor(@Nullable Language language, + @NotNull String group, + @NotNull String displayNameWithPath, + @NotNull EditorColorsScheme scheme, + @NotNull RainbowColorsInSchemeState rainbowState) { + myLanguage = language; + myDisplayName = displayNameWithPath; + myRainbowColorsInSchemaState = rainbowState; + myScheme = scheme; + myGroup = group; + } + + @Override + public String toString() { + return myDisplayName; + } + + @Override + public String getGroup() { + return myGroup; + } + + @Override + public String getType() { + return RainbowHighlighter.RAINBOW_TYPE; + } + + @Override + public EditorColorsScheme getScheme() { + return myScheme; + } + + @Override + public void apply(@NotNull EditorColorsScheme scheme) { + if (myLanguage == null) { + // call it once for 'Default Language' + myRainbowColorsInSchemaState.apply(scheme); + } + } + + @Override + public boolean isModified() { + return myRainbowColorsInSchemaState.isModified(myLanguage); + } + + public Language getLanguage() { + return myLanguage; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java new file mode 100644 index 000000000000..b02b2e81b087 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowColorsInSchemeState.java @@ -0,0 +1,84 @@ +/* + * 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.application.options.colors; + +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.lang.Language; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +public class RainbowColorsInSchemeState { + private final EditorColorsScheme myEditedScheme; + private final EditorColorsScheme myOriginalScheme; + + public RainbowColorsInSchemeState(@NotNull EditorColorsScheme editedScheme, + @NotNull EditorColorsScheme originalScheme) { + myEditedScheme = editedScheme; + myOriginalScheme = originalScheme; + } + + public void apply(@NotNull EditorColorsScheme scheme) { + if (scheme != myEditedScheme) { + scheme.getMetaProperties().clear(); + //noinspection UseOfPropertiesAsHashtable + scheme.getMetaProperties().putAll(myEditedScheme.getMetaProperties()); + for (TextAttributesKey key : RainbowHighlighter.RAINBOW_COLOR_KEYS) { + Color color = myEditedScheme.getAttributes(key).getForegroundColor(); + if (!color.equals(scheme.getAttributes(key).getForegroundColor()) ) { + scheme.setAttributes(key, RainbowHighlighter.createRainbowAttribute(color)); + } + } + updateRainbowMarkup(); + } + } + + private static void updateRainbowMarkup() { + Editor[] allEditors = EditorFactory.getInstance().getAllEditors(); + for (Editor editor : allEditors) { + final Project project = editor.getProject(); + if (project != null) { + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (file != null) { + DaemonCodeAnalyzer.getInstance(project).restart(file); + } + } + } + } + + public boolean isModified(@Nullable Language language) { + return (language == null && isRainbowColorsModified()) + || RainbowHighlighter.isRainbowEnabled(myEditedScheme, language) != RainbowHighlighter.isRainbowEnabled(myOriginalScheme, language); + } + + private boolean isRainbowColorsModified() { + for (TextAttributesKey key : RainbowHighlighter.RAINBOW_COLOR_KEYS) { + if (!myEditedScheme.getAttributes(key).equals(myOriginalScheme.getAttributes(key)) ) { + return true; + } + } + return false; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.form b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.form new file mode 100644 index 000000000000..0e8ddb02e857 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.form @@ -0,0 +1,135 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.java new file mode 100644 index 000000000000..4c36dcd3c73d --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/RainbowDescriptionPanel.java @@ -0,0 +1,180 @@ +/* + * 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.application.options.colors; + +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; +import com.intellij.openapi.options.OptionsBundle; +import com.intellij.openapi.ui.Messages; +import com.intellij.ui.ColorPanel; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.EventDispatcher; +import com.intellij.util.FontUtil; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.awt.event.ActionListener; + + +public class RainbowDescriptionPanel extends JPanel implements OptionsPanelImpl.ColorDescriptionPanel { + private final EventDispatcher myDispatcher = EventDispatcher.create(Listener.class); + + protected JPanel myPanel; + + private JTextPane myGradientLabel; + private JBLabel myLStop1; + private JBLabel myLStop2; + private JBLabel myLStop3; + private JBLabel myLStop4; + private JBLabel myLStop5; + private JBLabel[] myLStops = new JBLabel[]{myLStop1, myLStop2, myLStop3, myLStop4, myLStop5}; + + protected ColorPanel myStop1; + protected ColorPanel myStop2; + protected ColorPanel myStop3; + protected ColorPanel myStop4; + protected ColorPanel myStop5; + private ColorPanel[] myStops = new ColorPanel[]{myStop1, myStop2, myStop3, myStop4, myStop5}; + + private JBCheckBox myRainbow; + private JTextPane myInheritanceLabel; + private JBCheckBox myInheritAttributesBox; + + private final String myInheritedMessage; + private final String myOverrideMessage; + private final String myInheritedMessageTooltip; + + public RainbowDescriptionPanel() { + super(new BorderLayout()); + add(myPanel, BorderLayout.CENTER); + + setBorder(JBUI.Borders.empty(4, 0, 4, 4)); + + ActionListener actionListener = e -> myDispatcher.getMulticaster().onSettingsChanged(e); + for (JBCheckBox c : new JBCheckBox[]{myRainbow, myInheritAttributesBox}) { + c.addActionListener(actionListener); + } + for (ColorPanel c : new ColorPanel[]{myStop1, myStop2, myStop3, myStop4, myStop5}) { + c.addActionListener(actionListener); + } + + String languageDefaultPageID = OptionsBundle.message("options.language.defaults.display.name"); + String rainbowOptionsID = ApplicationBundle.message("rainbow.option.panel.display.name"); + myInheritedMessage = ApplicationBundle.message("label.inherited.gradient", + rainbowOptionsID, + languageDefaultPageID); + + myInheritedMessageTooltip = checkRightArrow(ApplicationBundle.message("label.inherited.gradient.tooltip", + rainbowOptionsID, + languageDefaultPageID)); + + myOverrideMessage = ApplicationBundle.message("label.override.gradient"); + HyperlinkListener listener = e -> myDispatcher.getMulticaster().onHyperLinkClicked(e); + + Messages.configureMessagePaneUi(myGradientLabel, myOverrideMessage, null); + myGradientLabel.addHyperlinkListener(listener); + + Messages.configureMessagePaneUi(myInheritanceLabel, + checkRightArrow(ApplicationBundle.message("label.rainbow.inheritance", + rainbowOptionsID, + rainbowOptionsID, + languageDefaultPageID)), + null); + myInheritanceLabel.setToolTipText(checkRightArrow(ApplicationBundle.message("label.rainbow.inheritance.tooltip", + rainbowOptionsID, + languageDefaultPageID))); + myInheritanceLabel.addHyperlinkListener(listener); + myInheritanceLabel.setBorder(JBUI.Borders.empty(4, 0, 4, 4)); + } + + @NotNull + private static String checkRightArrow(@NotNull String str) { + return str.replaceAll("->", FontUtil.rightArrow(UIUtil.getLabelFont())); + } + + @NotNull + @Override + public JComponent getPanel() { + return this; + } + + @Override + public void resetDefault() { + } + + @Override + public void reset(@NotNull EditorSchemeAttributeDescriptor attributeDescriptor) { + if (!(attributeDescriptor instanceof RainbowAttributeDescriptor)) return; + RainbowAttributeDescriptor descriptor = (RainbowAttributeDescriptor)attributeDescriptor; + + EditorColorsScheme editedColorsScheme = descriptor.getScheme(); + Boolean rainbowOn = RainbowHighlighter.isRainbowEnabled(editedColorsScheme, descriptor.getLanguage()); + boolean isInherited = false; + // the colors are editable only for default language + boolean isDefaultLanguage = descriptor.getLanguage() == null; + boolean isEnable = !ColorAndFontOptions.isReadOnly(editedColorsScheme); + if (rainbowOn == null) { + isInherited = true; + rainbowOn = RainbowHighlighter.isRainbowEnabled(editedColorsScheme, null); + } + myRainbow.setEnabled(isEnable && !isInherited); + myRainbow.setSelected(rainbowOn); + + for (int i = 0; i < myLStops.length; ++i) { + myLStops[i].setEnabled(isEnable && isDefaultLanguage); + myStops[i].setEnabled(rainbowOn); + myStops[i].setEditable(isEnable && isDefaultLanguage); + myStops[i].setSelectedColor(editedColorsScheme.getAttributes(RainbowHighlighter.RAINBOW_COLOR_KEYS[i]).getForegroundColor()); + } + + myInheritanceLabel.setVisible(!isDefaultLanguage); + myInheritAttributesBox.setEnabled(isEnable); + myInheritAttributesBox.setSelected(isInherited); + myInheritAttributesBox.setVisible(!isDefaultLanguage); + myGradientLabel.setText(isDefaultLanguage ? myOverrideMessage : myInheritedMessage); + myGradientLabel.setToolTipText(isDefaultLanguage ? null : myInheritedMessageTooltip); + } + + @Override + public void apply(@NotNull EditorSchemeAttributeDescriptor attributeDescriptor, EditorColorsScheme scheme) { + if (!(attributeDescriptor instanceof RainbowAttributeDescriptor)) return; + RainbowAttributeDescriptor descriptor = (RainbowAttributeDescriptor)attributeDescriptor; + + boolean isDefaultLanguage = descriptor.getLanguage() == null; + RainbowHighlighter.setRainbowEnabled(scheme, + descriptor.getLanguage(), + isDefaultLanguage ? Boolean.valueOf(myRainbow.isSelected()) + : myInheritAttributesBox.isSelected() ? null + : Boolean.valueOf(myRainbow.isSelected())); + + for (int i = 0; i < myStops.length; ++i) { + scheme.setAttributes(RainbowHighlighter.RAINBOW_COLOR_KEYS[i], RainbowHighlighter.createRainbowAttribute(myStops[i].getSelectedColor())); + } + descriptor.apply(scheme); + } + + @Override + public void addListener(@NotNull Listener listener) { + myDispatcher.addListener(listener); + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java index 0a53a8309df5..f8cfde8fe328 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java @@ -172,14 +172,11 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { } } - private void changeToScheme() { - updateDescription(false); - } - + @Deprecated public boolean updateDescription(boolean modified) { EditorColorsScheme scheme = myOptions.getSelectedScheme(); - if (modified && (ColorAndFontOptions.isReadOnly(scheme) || ColorSettingsUtil.isSharedScheme(scheme))) { + if (modified && ColorAndFontOptions.isReadOnly(scheme)) { return false; } @@ -201,8 +198,6 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { mySchemeComboBox.setSelectedItem(selectedSchemeBackup); setListLoaded(true); - changeToScheme(); - myDispatcher.getMulticaster().schemeChanged(this); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java b/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java index afe88048f6b4..401c9eb751c9 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/SimpleEditorPreview.java @@ -18,46 +18,53 @@ package com.intellij.application.options.colors; import com.intellij.application.options.colors.highlighting.HighlightData; import com.intellij.application.options.colors.highlighting.HighlightsExtractor; +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.codeInsight.daemon.UsedColors; import com.intellij.ide.highlighter.HighlighterFactory; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.ScrollType; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.event.CaretAdapter; import com.intellij.openapi.editor.event.CaretEvent; -import com.intellij.openapi.editor.event.CaretListener; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.highlighter.EditorHighlighter; import com.intellij.openapi.editor.highlighter.HighlighterIterator; +import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.options.colors.ColorSettingsPage; import com.intellij.openapi.options.colors.EditorHighlightingProvidingColorSettingsPage; +import com.intellij.openapi.options.colors.RainbowColorSettingsPage; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.tree.IElementType; import com.intellij.util.Alarm; import com.intellij.util.EventDispatcher; import com.intellij.util.ui.UIUtil; +import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; -public class SimpleEditorPreview implements PreviewPanel{ +public class SimpleEditorPreview implements PreviewPanel { private final ColorSettingsPage myPage; private final EditorEx myEditor; private final Alarm myBlinkingAlarm; - private final HighlightData[] myHighlightData; + private final List myHighlightData = new ArrayList<>(); private final ColorAndFontOptions myOptions; private final EventDispatcher myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class); + private final HighlightsExtractor myHighlightsExtractor; public SimpleEditorPreview(final ColorAndFontOptions options, final ColorSettingsPage page) { this(options, page, true); @@ -67,27 +74,27 @@ public class SimpleEditorPreview implements PreviewPanel{ myOptions = options; myPage = page; - String text = page.getDemoText(); - - HighlightsExtractor extractant2 = new HighlightsExtractor(page.getAdditionalHighlightingTagToDescriptorMap()); - List highlights = new ArrayList<>(); - String stripped = extractant2.extractHighlights(text, highlights); - myHighlightData = highlights.toArray(new HighlightData[highlights.size()]); - int selectedLine = -1; - myEditor = (EditorEx)FontEditorPreview.createPreviewEditor(stripped, 10, 3, selectedLine, myOptions, false); + myHighlightsExtractor = new HighlightsExtractor(page.getAdditionalHighlightingTagToDescriptorMap()); + myEditor = (EditorEx)FontEditorPreview.createPreviewEditor( + myHighlightsExtractor.extractHighlights(page.getDemoText(), myHighlightData), // text without tags + 10, 3, -1, myOptions, false); FontEditorPreview.installTrafficLights(myEditor); myBlinkingAlarm = new Alarm().setActivationComponent(myEditor.getComponent()); if (navigatable) { - addMouseMotionListener(myEditor, page.getHighlighter(), myHighlightData, false); + myEditor.getContentComponent().addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + navigate(false, myEditor.xyToLogicalPosition(new Point(e.getX(), e.getY()))); + } + }); - CaretListener listener = new CaretAdapter() { + myEditor.getCaretModel().addCaretListener(new CaretAdapter() { @Override public void caretPositionChanged(CaretEvent e) { - navigate(myEditor, true, e.getNewPosition(), page.getHighlighter(), myHighlightData, false); + navigate(true, e.getNewPosition()); } - }; - myEditor.getCaretModel().addCaretListener(listener); + }); } } @@ -95,61 +102,62 @@ public class SimpleEditorPreview implements PreviewPanel{ return myEditor; } - private void addMouseMotionListener(final Editor view, - final SyntaxHighlighter highlighter, - final HighlightData[] data, final boolean isBackgroundImportant) { - view.getContentComponent().addMouseMotionListener(new MouseMotionAdapter() { - @Override - public void mouseMoved(MouseEvent e) { - LogicalPosition pos = view.xyToLogicalPosition(new Point(e.getX(), e.getY())); - navigate(view, false, pos, highlighter, data, isBackgroundImportant); - } - }); + public void setDemoText(final String text) { + myEditor.getSelectionModel().removeSelection(); + myHighlightData.clear(); + myEditor.getDocument().setText(myHighlightsExtractor.extractHighlights(text, myHighlightData)); } - private void navigate(final Editor editor, boolean select, - LogicalPosition pos, - final SyntaxHighlighter highlighter, - final HighlightData[] data, final boolean isBackgroundImportant) { - int offset = editor.logicalPositionToOffset(pos); + private void navigate(boolean select, @NotNull final LogicalPosition pos) { + int offset = myEditor.logicalPositionToOffset(pos); + final SyntaxHighlighter highlighter = myPage.getHighlighter(); - if (!isBackgroundImportant && editor.offsetToLogicalPosition(offset).column != pos.column) { - if (!select) { - ClickNavigator.setCursor(editor, Cursor.TEXT_CURSOR); - return; - } + String type = null; + HighlightData highlightData = getDataFromOffset(offset); + if (highlightData != null) { + // tag-based navigation first + type = RainbowHighlighter.isRainbowTempKey(highlightData.getHighlightKey()) + ? RainbowHighlighter.RAINBOW_TYPE + : highlightData.getHighlightType(); + } + else { + // if failed, try the highlighter-based navigation + type = selectItem(((EditorEx)myEditor).getHighlighter().createIterator(offset), highlighter); } - if (data != null) { - for (HighlightData highlightData : data) { - if (ClickNavigator.highlightDataContainsOffset(highlightData, editor.logicalPositionToOffset(pos))) { - if (!select) { - ClickNavigator.setCursor(editor, Cursor.HAND_CURSOR); - } - else { - myDispatcher.getMulticaster().selectionInPreviewChanged(highlightData.getHighlightType()); - } - return; - } - } - } + setCursor(type == null ? Cursor.TEXT_CURSOR : Cursor.HAND_CURSOR); - if (highlighter != null) { - HighlighterIterator itr = ((EditorEx)editor).getHighlighter().createIterator(offset); - selectItem(itr, highlighter, select); - ClickNavigator.setCursor(editor, select ? Cursor.TEXT_CURSOR : Cursor.HAND_CURSOR); - } - } - - private void selectItem(HighlighterIterator itr, SyntaxHighlighter highlighter, final boolean select) { - IElementType tokenType = itr.getTokenType(); - if (tokenType == null) return; - String type = ClickNavigator.highlightingTypeFromTokenType(tokenType, highlighter); - if (select) { + if (select && type != null) { myDispatcher.getMulticaster().selectionInPreviewChanged(type); } } + @Nullable + private HighlightData getDataFromOffset(int offset) { + for (HighlightData highlightData : myHighlightData) { + if (offset >= highlightData.getStartOffset() && offset <= highlightData.getEndOffset()) { + return highlightData; + } + } + return null; + } + + @Nullable + private static String selectItem(HighlighterIterator itr, SyntaxHighlighter highlighter) { + IElementType tokenType = itr.getTokenType(); + if (tokenType == null) return null; + + TextAttributesKey[] highlights = highlighter.getTokenHighlights(tokenType); + String s = null; + for (int i = highlights.length - 1; i >= 0; i--) { + if (highlights[i] != HighlighterColors.TEXT) { + s = highlights[i].getExternalName(); + break; + } + } + return s == null ? HighlighterColors.TEXT.getExternalName() : s; + } + @Override public JComponent getPanel() { return myEditor.getComponent(); @@ -174,16 +182,14 @@ public class SimpleEditorPreview implements PreviewPanel{ updateHighlighters(); myEditor.reinitSettings(); - } private void updateHighlighters() { UIUtil.invokeLaterIfNeeded(() -> { if (myEditor.isDisposed()) return; myEditor.getMarkupModel().removeAllHighlighters(); - HighlightData[] datum = myHighlightData; final Map displayText = ColorSettingsUtil.keyToDisplayTextMap(myPage); - for (final HighlightData data : datum) { + for (final HighlightData data : myHighlightData) { data.addHighlToView(myEditor, myOptions.getSelectedScheme(), displayText); } }); @@ -193,46 +199,48 @@ public class SimpleEditorPreview implements PreviewPanel{ @Override public void blinkSelectedHighlightType(Object description) { - if (description instanceof EditorSchemeAttributeDescriptor){ + if (description instanceof EditorSchemeAttributeDescriptor) { String type = ((EditorSchemeAttributeDescriptor)description).getType(); List highlights = startBlinkingHighlights(myEditor, - myHighlightData, type, + type, myPage.getHighlighter(), true, myBlinkingAlarm, BLINK_COUNT, myPage); - scrollHighlightInView(highlights, myEditor); + scrollHighlightInView(highlights); } } - private static void scrollHighlightInView(final List highlightDatas, final Editor editor) { + void scrollHighlightInView(@Nullable final List highlightDatas) { + if (highlightDatas == null) return; + boolean needScroll = true; int minOffset = Integer.MAX_VALUE; - for(HighlightData data: highlightDatas) { - if (isOffsetVisible(editor, data.getStartOffset())) { + for (HighlightData data : highlightDatas) { + if (isOffsetVisible(data.getStartOffset())) { needScroll = false; break; } minOffset = Math.min(minOffset, data.getStartOffset()); } if (needScroll && minOffset != Integer.MAX_VALUE) { - LogicalPosition pos = editor.offsetToLogicalPosition(minOffset); - editor.getScrollingModel().scrollTo(pos, ScrollType.MAKE_VISIBLE); + LogicalPosition pos = myEditor.offsetToLogicalPosition(minOffset); + myEditor.getScrollingModel().scrollTo(pos, ScrollType.MAKE_VISIBLE); } } - private static boolean isOffsetVisible(final Editor editor, final int startOffset) { - Rectangle visibleArea = editor.getScrollingModel().getVisibleArea(); - Point point = editor.logicalPositionToXY(editor.offsetToLogicalPosition(startOffset)); - return point.y >= visibleArea.y && point.y < (visibleArea.y + visibleArea.height); + private boolean isOffsetVisible(final int startOffset) { + return myEditor + .getScrollingModel() + .getVisibleArea() + .contains(myEditor.logicalPositionToXY(myEditor.offsetToLogicalPosition(startOffset))); } - private void stopBlinking() { + public void stopBlinking() { myBlinkingAlarm.cancelAllRequests(); } private List startBlinkingHighlights(final EditorEx editor, - final HighlightData[] highlightDatum, final String attrKey, final SyntaxHighlighter highlighter, final boolean show, @@ -244,14 +252,13 @@ public class SimpleEditorPreview implements PreviewPanel{ boolean found = false; List highlights = new ArrayList<>(); List matchingHighlights = new ArrayList<>(); - for (int i = 0; highlightDatum != null && i < highlightDatum.length; i++) { - HighlightData highlightData = highlightDatum[i]; + for (HighlightData highlightData : myHighlightData) { String type = highlightData.getHighlightType(); highlights.add(highlightData); if (show && type.equals(attrKey)) { highlightData = - new HighlightData(highlightData.getStartOffset(), highlightData.getEndOffset(), - CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES); + new HighlightData(highlightData.getStartOffset(), highlightData.getEndOffset(), + CodeInsightColors.BLINKING_HIGHLIGHTS_ATTRIBUTES); highlights.add(highlightData); matchingHighlights.add(highlightData); found = true; @@ -294,7 +301,7 @@ public class SimpleEditorPreview implements PreviewPanel{ } } alarm.cancelAllRequests(); - alarm.addComponentRequest(() -> startBlinkingHighlights(editor, highlightDatum, attrKey, highlighter, !show, alarm, count - 1, page), 400); + alarm.addComponentRequest(() -> startBlinkingHighlights(editor, attrKey, highlighter, !show, alarm, count - 1, page), 400); return matchingHighlights; } @@ -309,6 +316,84 @@ public class SimpleEditorPreview implements PreviewPanel{ EditorFactory editorFactory = EditorFactory.getInstance(); editorFactory.releaseEditor(myEditor); stopBlinking(); + } + private void setCursor(@JdkConstants.CursorType int type) { + final Cursor cursor = type == Cursor.TEXT_CURSOR ? UIUtil.getTextCursor(myEditor.getBackgroundColor()) + : Cursor.getPredefinedCursor(type); + myEditor.getContentComponent().setCursor(cursor); + } + + public void setupRainbow(@NotNull EditorColorsScheme colorsScheme, @NotNull RainbowColorSettingsPage page) { + final List initialMarkup = new ArrayList<>(); + myHighlightsExtractor.extractHighlights(page.getDemoText(), initialMarkup); + + final List rainbowMarkup = setupRainbowHighlighting( + page, + initialMarkup, + new RainbowHighlighter(colorsScheme).getRainbowTempKeys(), + RainbowHighlighter.isRainbowEnabledWithInheritance(colorsScheme, page.getLanguage())); + + myHighlightData.clear(); + myHighlightData.addAll(rainbowMarkup); + } + + @NotNull + private List setupRainbowHighlighting(@NotNull final RainbowColorSettingsPage page, + @NotNull final List initialMarkup, + @NotNull final TextAttributesKey[] rainbowTempKeys, + boolean isRainbowOn) { + int colorCount = rainbowTempKeys.length; + if (colorCount == 0) { + return initialMarkup; + } + List rainbowMarkup = new ArrayList<>(); + + int tempKeyIndex = 0; + for (HighlightData d : initialMarkup) { + final TextAttributesKey highlightKey = d.getHighlightKey(); + final boolean rainbowType = page.isRainbowType(highlightKey); + final boolean rainbowDemoType = highlightKey == RainbowHighlighter.RAINBOW_GRADIENT_DEMO; + if (rainbowType || rainbowDemoType) { + final HighlightData rainbowAnchor = new HighlightData(d.getStartOffset(), d.getEndOffset(), RainbowHighlighter.RAINBOW_ANCHOR); + if (isRainbowOn) { + // rainbow on + HighlightData rainbowTemp; + if (rainbowType) { + rainbowTemp = getRainbowTemp(rainbowTempKeys, d.getStartOffset(), d.getEndOffset()); + } + else { + rainbowTemp = new HighlightData(d.getStartOffset(), d.getEndOffset(), rainbowTempKeys[tempKeyIndex++ % colorCount]); + } + rainbowMarkup.add(rainbowTemp); + rainbowMarkup.add(rainbowAnchor); + rainbowMarkup.add(rainbowTemp); + } + else { + // rainbow off + if (rainbowType) { + rainbowMarkup.add(d); + rainbowMarkup.add(rainbowAnchor); + rainbowMarkup.add(d); + } + else { + rainbowMarkup.add(rainbowAnchor); + } + } + } + else if (!(RainbowHighlighter.isRainbowTempKey(highlightKey) || highlightKey == RainbowHighlighter.RAINBOW_ANCHOR)) { + // filter rainbow RAINBOW_TEMP and RAINBOW_ANCHOR + rainbowMarkup.add(d); + } + } + return rainbowMarkup; + } + + @NotNull + private HighlightData getRainbowTemp(@NotNull TextAttributesKey[] rainbowTempKeys, + int startOffset, int endOffset) { + String id = myEditor.getDocument().getText(TextRange.create(startOffset, endOffset)); + int index = UsedColors.getOrAddColorIndex((EditorImpl)myEditor, id, rainbowTempKeys.length); + return new HighlightData(startOffset, endOffset, rainbowTempKeys[index]); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/highlighting/HighlightData.java b/platform/lang-impl/src/com/intellij/application/options/colors/highlighting/HighlightData.java index 7d64bc12bd64..499605ab18b9 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/highlighting/HighlightData.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/highlighting/HighlightData.java @@ -92,4 +92,8 @@ public final class HighlightData { public String getHighlightType() { return myHighlightType.getExternalName(); } + + public TextAttributesKey getHighlightKey() { + return myHighlightType; + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffColorDescriptionPanel.java b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffColorDescriptionPanel.java index ce5dd89fec4e..97207ef41378 100644 --- a/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffColorDescriptionPanel.java +++ b/platform/lang-impl/src/com/intellij/openapi/diff/impl/settings/DiffColorDescriptionPanel.java @@ -21,6 +21,7 @@ import com.intellij.application.options.colors.ColorAndFontOptions; import com.intellij.application.options.colors.OptionsPanelImpl; import com.intellij.diff.util.TextDiffTypeFactory; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.ui.ColorPanel; import com.intellij.ui.JBColor; @@ -95,7 +96,10 @@ class DiffColorDescriptionPanel extends JPanel implements OptionsPanelImpl.Color myInheritIgnoredCheckBox.setSelected(false); } - public void reset(@NotNull ColorAndFontDescription description) { + public void reset(@NotNull EditorSchemeAttributeDescriptor attrDescription) { + if (!(attrDescription instanceof ColorAndFontDescription)) return; + ColorAndFontDescription description = (ColorAndFontDescription)attrDescription; + Color backgroundColor = getBackgroundColor(description); Color ignoredColor = getIgnoredColor(description); Color stripeMarkColor = getStripeMarkColor(description); @@ -112,7 +116,10 @@ class DiffColorDescriptionPanel extends JPanel implements OptionsPanelImpl.Color myInheritIgnoredCheckBox.setSelected(inheritIgnored); } - public void apply(@NotNull ColorAndFontDescription description, EditorColorsScheme scheme) { + public void apply(@NotNull EditorSchemeAttributeDescriptor attrDescription, EditorColorsScheme scheme) { + if (!(attrDescription instanceof ColorAndFontDescription)) return; + ColorAndFontDescription description = (ColorAndFontDescription)attrDescription; + description.setBackgroundChecked(true); description.setForegroundChecked(true); description.setErrorStripeChecked(true); diff --git a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/DefaultLanguageColorsPage.java b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/DefaultLanguageColorsPage.java index 6fe557e2cad2..2f783d7732dc 100644 --- a/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/DefaultLanguageColorsPage.java +++ b/platform/lang-impl/src/com/intellij/openapi/options/colors/pages/DefaultLanguageColorsPage.java @@ -15,6 +15,9 @@ */ package com.intellij.openapi.options.colors.pages; +import com.intellij.codeHighlighting.RainbowHighlighter; +import com.intellij.lang.Language; +import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.openapi.editor.HighlighterColors; import com.intellij.openapi.editor.colors.TextAttributesKey; @@ -24,7 +27,7 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.options.OptionsBundle; import com.intellij.openapi.options.colors.AttributesDescriptor; import com.intellij.openapi.options.colors.ColorDescriptor; -import com.intellij.openapi.options.colors.ColorSettingsPage; +import com.intellij.openapi.options.colors.RainbowColorSettingsPage; import com.intellij.psi.codeStyle.DisplayPriority; import com.intellij.psi.codeStyle.DisplayPrioritySortable; import org.jetbrains.annotations.NonNls; @@ -32,7 +35,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.HashMap; import java.util.Map; /** @@ -40,9 +42,8 @@ import java.util.Map; * * @author Rustam Vishnyakov */ -public class DefaultLanguageColorsPage implements ColorSettingsPage, DisplayPrioritySortable { - - @NonNls private static final Map TAG_HIGHLIGHTING_MAP = new HashMap<>(); +public class DefaultLanguageColorsPage implements RainbowColorSettingsPage, DisplayPrioritySortable { + @NonNls private static final Map TAG_HIGHLIGHTING_MAP = RainbowHighlighter.createRainbowHLM(); private final static TextAttributesKey FAKE_BAD_CHAR = TextAttributesKey.createTextAttributesKey("FAKE_BAD_CHAR", HighlighterColors.BAD_CHARACTER); @@ -203,17 +204,22 @@ public class DefaultLanguageColorsPage implements ColorSettingsPage, DisplayPrio "[ Brackets ]\n" + "// Line comment\n" + "/* Block comment */\n" + - "/** \n" + - " * Doc comment\n" + - " * @tag Markup\n" + - " * @param param_name documentation\n" + - " */\n" + "\n" + "predefined_symbol()\n" + "CONSTANT\n" + "Global variable\n" + - "Function declaration (parameter)\n" + - " Local variable\n" + + "/** \n" + + " * Doc comment\n" + + " * @tag Markup\n" + + " * " + ApplicationBundle.message("rainbow.option.panel.display.name") + ":\n" + + " * " + RainbowHighlighter.generatePaletteExample() + "\n" + + " * @param parameter1 documentation\n" + + " * @param parameter2 documentation\n" + + " * @param parameter3 documentation\n" + + " * @param parameter4 documentation\n" + + " */\n" + + "Function declaration (parameter1 parameter2 parameter3 parameter4)\n" + + " Local variable1 variable2 variable3 variable4\n" + "Function call()\n" + "Interface Name\n" + "@Metadata\n" + @@ -256,4 +262,17 @@ public class DefaultLanguageColorsPage implements ColorSettingsPage, DisplayPrio public DisplayPriority getPriority() { return DisplayPriority.GENERAL_SETTINGS; } + + @Override + public boolean isRainbowType(TextAttributesKey type) { + return DefaultLanguageHighlighterColors.LOCAL_VARIABLE.equals(type) + || DefaultLanguageHighlighterColors.PARAMETER.equals(type) + || DefaultLanguageHighlighterColors.DOC_COMMENT_TAG_VALUE.equals(type); + } + + @Nullable + @Override + public Language getLanguage() { + return null; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java index 01fe0814f2c3..2105f6bba288 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/DelegateColorScheme.java @@ -23,6 +23,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.Properties; /** * User: spLeaner @@ -197,4 +198,10 @@ public abstract class DelegateColorScheme implements EditorColorsScheme { public void setConsoleLineSpacing(float lineSpacing) { myDelegate.setConsoleLineSpacing(lineSpacing); } + + @NotNull + @Override + public Properties getMetaProperties() { + return myDelegate.getMetaProperties(); + } } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index 5c7ec4049d30..8fa5a4e63a04 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -749,4 +749,17 @@ quarantine.dialog.message=OS marked this folder as 'quarantined', probably becau quarantine.clean.progress=Cleaning quarantined status for {0} quarantine.error.group=Quarantine Cleaner quarantine.error.title=Warning -quarantine.error.message=Error cleaning quarantine status \ No newline at end of file +quarantine.error.message=Error cleaning quarantine status + +rainbow.option.panel.display.name=Semantic highlighting +label.override.gradient=Override gradient: +label.inherited.gradient=Inherited from {1} gradient: +label.inherited.gradient.tooltip=''{0}->Override gradient'' from
''{1}'' section +checkbox.stop.1=Stop #1 +checkbox.stop.2=Stop #2 +checkbox.stop.3=Stop #3 +checkbox.stop.4=Stop #4 +checkbox.stop.5=Stop #5 +checkbox.rainbow=Unique color for each parameter
and local variable
Chosen from generated gradient +label.rainbow.inheritance=
''{0}->Unique color''
of {2} +label.rainbow.inheritance.tooltip=''{0}->Unique color'' from
''{1}'' section \ No newline at end of file diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml index 2abe4a25a8f6..656a01bfe9d5 100644 --- a/platform/platform-resources/src/DefaultColorSchemesManager.xml +++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml @@ -1024,6 +1024,31 @@ + + + + + @@ -2086,6 +2111,31 @@ + + + + + diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index b24c40004be3..acd2aa193454 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -67,6 +67,8 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.DocCommandGroupId; import com.intellij.openapi.editor.actionSystem.EditorActionManager; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.DocumentImpl; @@ -1738,10 +1740,10 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig @Override public void testRainbow(@NotNull String fileName, @NotNull String text, boolean isRainbowOn, boolean withColor) { - RegistryValue registryValue = Registry.get("editor.rainbow.identifiers"); - final boolean rainbowColors = registryValue.asBoolean(); + final EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme(); + final boolean isRainbowOnInScheme = RainbowHighlighter.isRainbowEnabled(globalScheme, null); try { - registryValue.setValue(isRainbowOn); + RainbowHighlighter.setRainbowEnabled(globalScheme, null, isRainbowOn); configureByText(fileName, text.replaceAll("<" + RAINBOW + "(\\scolor=\'[^\']*\')?>", "").replace("", "")); Assert.assertEquals(text, getHighlightingDescription(ContainerUtil.filter(doHighlighting(), @@ -1749,7 +1751,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig withColor)); } finally { - registryValue.setValue(rainbowColors); + RainbowHighlighter.setRainbowEnabled(globalScheme, null, isRainbowOnInScheme); } } diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java index 8360423f86e9..105fc26f600d 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java @@ -489,6 +489,12 @@ public class JBTerminalSystemSettingsProvider extends DefaultTabbedSettingsProvi public void setConsoleLineSpacing(float lineSpacing) { getGlobal().setConsoleLineSpacing(lineSpacing); } + + @NotNull + @Override + public Properties getMetaProperties() { + return myGlobalScheme.getMetaProperties(); + } } public void addListener(TerminalSettingsListener listener) {