import com.intellij.openapi.editor.colors.TextAttributesScheme;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringHash;
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;
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!
static {
RAINBOW_COLOR_KEYS[i] = TextAttributesKey.createTextAttributesKey("RAINBOW_COLOR" + i, textAttributes);
}
}
+ public final static String RAINBOW_TYPE = "rainbow";
+ private final static String RAINBOW_TEMP_PREF = "RAINBOW_TEMP_";
@NotNull private final TextAttributesScheme myColorsScheme;
@NotNull private final Color[] myRainbowColors;
Registry.get("editor.rainbow.identifiers").setValue(enabled);
}
+ public static int hashColor(@NotNull String name, int colorsCount) {
+ return Math.abs(StringHash.murmur(name, 0x55AA)) % colorsCount;
+ }
+
+ public static int getColorIndex(@NotNull int[] index2usage, int hashedIndex, int colorsCount) {
+ int minIndex1 = indexOfMin(index2usage, hashedIndex, colorsCount);
+ int minIndex2 = indexOfMin(index2usage, 0, hashedIndex);
+ return index2usage[minIndex1] <= index2usage[minIndex2] ? minIndex1 : minIndex2;
+ }
+
+ @Contract(pure = true)
+ private static int indexOfMin(@NotNull int[] index2usage, int start, int end) {
+ int min = Integer.MAX_VALUE;
+ int minIndex = start;
+ for (int i = start; i < end; i++) {
+ int value = index2usage[i];
+ if (value < min) {
+ min = value;
+ minIndex = i;
+ }
+ }
+ return minIndex;
+ }
+
@NotNull
+ @Contract(pure = true)
private Color calculateForeground(int colorIndex) {
return myRainbowColors[colorIndex];
}
return registryColors.stream().map(s -> ColorUtil.fromHex(s.trim())).toArray(Color[]::new);
}
- List<Color> foregroundColors = ContainerUtil.map(RAINBOW_COLOR_KEYS, key -> colorsScheme.getAttributes(key).getForegroundColor());
- List<Color> colors = ColorGenerator.generateLinearColorSequence(foregroundColors, RAINBOW_COLORS_BETWEEN);
+ List<Color> stopColors = ContainerUtil.map(RAINBOW_COLOR_KEYS, key -> colorsScheme.getAttributes(key).getForegroundColor());
+ List<Color> colors = ColorGenerator.generateLinearColorSequence(stopColors, RAINBOW_COLORS_BETWEEN);
return colors.toArray(new Color[colors.size()]);
}
+ @NotNull
+ public TextAttributesKey[] getRainbowTempKeys() {
+ TextAttributesKey[] keys = new TextAttributesKey[myRainbowColors.length];
+ for (int i = 0; i < myRainbowColors.length; ++i) {
+ 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();
}
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.NotNull;
while (true) {
Object newColors;
if (data == null) {
- colorIndex = hashColor(name, colorsCount);
+ colorIndex = RainbowHighlighter.hashColor(name, colorsCount);
newColors = new UsedColor(name, colorIndex); // put an object instead of array to save space
}
else if (data instanceof UsedColor) {
newColors = null; // found, no need to create new
}
else {
- int hashedIndex = hashColor(name, colorsCount);
+ int hashedIndex = RainbowHighlighter.hashColor(name, colorsCount);
if (hashedIndex == usedColor.index) hashedIndex = (hashedIndex + 1) % colorsCount;
colorIndex = hashedIndex;
UsedColor newColor = new UsedColor(name, colorIndex);
}
else {
colorIndex = -1;
- int hashedIndex = hashColor(name, colorsCount);
+ int hashedIndex = RainbowHighlighter.hashColor(name, colorsCount);
int[] index2usage = new int[colorsCount];
UsedColor[] usedColors = (UsedColor[])data;
for (UsedColor usedColor : usedColors) {
}
}
if (colorIndex == -1) {
- int minIndex1 = indexOfMin(index2usage, hashedIndex, colorsCount);
- int minIndex2 = indexOfMin(index2usage, 0, hashedIndex);
- colorIndex = index2usage[minIndex1] <= index2usage[minIndex2] ? minIndex1 : minIndex2;
+ colorIndex = RainbowHighlighter.getColorIndex(index2usage, hashedIndex, colorsCount);
UsedColor newColor = new UsedColor(name, colorIndex);
newColors = ArrayUtil.append(usedColors, newColor);
}
return colorIndex;
}
-
- private static int hashColor(@NotNull String name, int colorsCount) {
- return Math.abs(StringHash.murmur(name, 0x55AA)) % colorsCount;
- }
-
- private static int indexOfMin(@NotNull int[] values, int start, int end) {
- int min = Integer.MAX_VALUE;
- int minIndex = start;
- for (int i = start; i < end; i++) {
- int value = values[i];
- if (value < min) {
- min = value;
- minIndex = i;
- }
- }
- return minIndex;
- }
}
@Nullable List<HighlightData> showLineData,
@NotNull List<HighlightData> data,
@NotNull RainbowHighlighter rainbowHighlighter,
- @NotNull List<TextAttributesKey> rainbowTempKeys) {
- if (!rainbowTempKeys.isEmpty()) {
- List<HighlightData> newData = new ArrayList<HighlightData>();
+ @NotNull TextAttributesKey[] rainbowTempKeys) {
+ int colorCount = rainbowTempKeys.length;
+ if (colorCount != 0) {
+ List<HighlightData> newData = new ArrayList<>();
if (showLineData != null) newData.addAll(showLineData);
- HashMap<String, Integer> id2index = new HashMap<String, Integer>();
-
+ int[] index2usage = new int[colorCount];
for (HighlightData d : data) {
if (((RainbowColorSettingsPage)myPage).isRainbowType(d.getHighlightKey())) {
String id = document.getText(TextRange.create(d.getStartOffset(), d.getEndOffset()));
- int index = rainbowHighlighter.getColorIndex(id2index, id, RainbowHighlighter.getRainbowHash(id));
- HighlightData rainbow = new HighlightData(d.getStartOffset(), d.getEndOffset(), rainbowTempKeys.get(index));
+ int index = RainbowHighlighter.getColorIndex(index2usage, RainbowHighlighter.hashColor(id, colorCount), colorCount);
+ ++index2usage[index];
+ HighlightData rainbow = new HighlightData(d.getStartOffset(), d.getEndOffset(), rainbowTempKeys[index]);
//fixme: twisted coloring in editor. We need add rainbow-tag twice.
newData.add(rainbow);
newData.add(d);
newData.add(rainbow);
}
- else if (!RainbowHighlighter.isRainbowTempKey(d.getHighlightKey())) {
- newData.add(d);
- }
- }
- data.clear();
- data.addAll(newData);
- }
- }
-
- private static void removeRainbowHighlighting(@NotNull List<HighlightData> data) {
- List<TextAttributesKey> keys = RainbowHighlighter.getRainbowKeys();
- if (!keys.isEmpty()) {
- List<HighlightData> newData = new ArrayList<HighlightData>();
- for (HighlightData d : data) {
- if (!keys.contains(d.getHighlightKey())) {
+ else {
newData.add(d);
}
}
if (myPage instanceof RainbowColorSettingsPage && myRainbowPanel.myGlobalState.isRainbowOn()) {
RainbowHighlighter highlighter = new RainbowHighlighter(descriptor.getScheme());
- List<TextAttributesKey> tempKeys = highlighter.getRainbowTempKeys();
+ TextAttributesKey[] tempKeys = highlighter.getRainbowTempKeys();
EditorEx editor = simpleEditorPreview.getEditor();
if (myActive == myRainbowPanel) {
Pair<String, List<HighlightData>> demo = getColorDemoLine(highlighter, tempKeys);
}
else {
simpleEditorPreview.setDemoText(demoText);
- removeRainbowHighlighting(simpleEditorPreview.getHighlightDataForExtension());
}
simpleEditorPreview.updateView();
}
@NotNull
- private static Pair<String, List<HighlightData>> getColorDemoLine(RainbowHighlighter highlighter, List<TextAttributesKey> tempKeys) {
+ private static Pair<String, List<HighlightData>> getColorDemoLine(RainbowHighlighter highlighter, TextAttributesKey[] tempKeys) {
int colorsCount = highlighter.getColorsCount();
- int stopCount = RainbowHighlighter.getRainbowKeys().size();
- List<HighlightData> markup = new ArrayList<HighlightData>(colorsCount);
+ int stopCount = RainbowHighlighter.RAINBOW_COLOR_KEYS.length;
+ List<HighlightData> markup = new ArrayList<>(colorsCount);
StringBuilder sb = new StringBuilder();
int pos = 0;
int i = 0;
}
public Color getDefaultColor(int index) {
- return RainbowHighlighter.getRainbowKeys().get(index).getDefaultAttributes().getForegroundColor();
+ return RainbowHighlighter.RAINBOW_COLOR_KEYS[index].getDefaultAttributes().getForegroundColor();
}
public static class RainbowInSchemeState {
private final List<Pair<Boolean, Color>> myRainbowState = new ArrayList<>();
public RainbowInSchemeState(@NotNull EditorColorsScheme scheme) {
- for (TextAttributesKey rainbowKey : RainbowHighlighter.getRainbowKeys()) {
+ for (TextAttributesKey rainbowKey : RainbowHighlighter.RAINBOW_COLOR_KEYS) {
myRainbowState.add(getColorStateFromScheme(scheme, rainbowKey));
}
}
public void apply(@NotNull EditorColorsScheme scheme) {
int i = 0;
- for (TextAttributesKey rainbowKey : RainbowHighlighter.getRainbowKeys()) {
+ for (TextAttributesKey rainbowKey : RainbowHighlighter.RAINBOW_COLOR_KEYS) {
Pair<Boolean, Color> pair = myRainbowState.get(i);
scheme.setAttributes(rainbowKey, pair.first ? new TextAttributes(pair.second, null, null, null, Font.PLAIN)
: rainbowKey.getDefaultAttributes());