IDEA-152258 IDEA-134212 vcs: add VCS color settings

* allow to configure colors of vcs annotations
* generate annotations colors from couple of given anchors
* move LST gutter colors settings from `General` group
* add preview for LST markers
This commit is contained in:
Aleksey Pivovarov
2016-04-13 18:07:59 +03:00
committed by Aleksey Pivovarov
parent f487eba3f4
commit 9882d1536d
12 changed files with 554 additions and 40 deletions
@@ -115,15 +115,8 @@ public class GeneralColorsPage implements ColorSettingsPage, InspectionColorSett
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.indent.guide"), EditorColors.INDENT_GUIDE_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.indent.guide.selected"), EditorColors.SELECTED_INDENT_GUIDE_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.line.number"), EditorColors.LINE_NUMBERS_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations"), EditorColors.ANNOTATIONS_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations.merged"), EditorColors.ANNOTATIONS_MERGED_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.tearline"), EditorColors.TEARLINE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.tearline.selected"), EditorColors.SELECTED_TEARLINE_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.added.lines"), EditorColors.ADDED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.modified.lines"), EditorColors.MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.deleted.lines"), EditorColors.DELETED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.whitespaces.modified.lines"), EditorColors.WHITESPACES_MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.border.lines"), EditorColors.BORDER_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND),
new ColorDescriptor(OptionsBundle.message("options.java.color.descriptor.method.separator.color"), CodeInsightColors.METHOD_SEPARATORS_COLOR, ColorDescriptor.Kind.FOREGROUND),
new ColorDescriptor(OptionsBundle.message("options.general.color.soft.wrap.sign"), EditorColors.SOFT_WRAP_SIGN_COLOR, ColorDescriptor.Kind.FOREGROUND),
};
@@ -549,6 +549,7 @@ checkbox.font.italic=Italic
label.font.type=Font
label.inherit.attributes=Use inherited attributes
title.diff=Diff \\& Merge
title.vcs=VCS
title.file.status=File Status
title.scope.based=By Scope
title.colors.and.fonts=Colors \\& Fonts
@@ -117,7 +117,7 @@ options.xml.attribute.descriptor.descriptor.entity,reference=Entity reference
#Color descriptors
options.general.color.descriptor.background.in.readonly.files=Text//Background in readonly files
options.general.color.descriptor.readonly.fragment.background=Text//Readonly fragment background
options.general.color.descriptor.gutter.background=Gutter//Background
options.general.color.descriptor.gutter.background=Editor//Gutter background
options.general.color.descriptor.notification.background=Editor//Notification background
options.general.color.descriptor.selection.background=Editor//Selection background
options.general.color.descriptor.selection.foreground=Editor//Selection foreground
@@ -128,15 +128,16 @@ options.general.color.descriptor.whitespaces=Text//Whitespaces
options.general.color.descriptor.indent.guide=Code//Vertical indent guide
options.general.color.descriptor.indent.guide.selected=Code//Selected vertical indent guide
options.general.color.descriptor.line.number=Code//Line number
options.general.color.descriptor.vcs.annotations=VCS Annotations//Regular
options.general.color.descriptor.vcs.annotations.merged=VCS Annotations//Merged from
options.general.color.descriptor.vcs.annotations=VCS Annotations//Foreground
options.general.color.descriptor.vcs.annotations.merged=VCS Annotations//Foreground for merged commits (SVN only)
options.general.color.descriptor.vcs.annotations.color.n=VCS Annotations//Background color #{0}
options.general.color.descriptor.tearline=Editor//Tear line
options.general.color.descriptor.tearline.selected=Editor//Tear line selection
options.general.color.descriptor.added.lines=Gutter//Added lines
options.general.color.descriptor.modified.lines=Gutter//Modified lines
options.general.color.descriptor.deleted.lines=Gutter//Deleted lines
options.general.color.descriptor.whitespaces.modified.lines=Gutter//Lines with whitespace-only modifications
options.general.color.descriptor.border.lines=Gutter//Border for changed lines
options.general.color.descriptor.added.lines=Editor Gutter//Added lines
options.general.color.descriptor.modified.lines=Editor Gutter//Modified lines
options.general.color.descriptor.deleted.lines=Editor Gutter//Deleted lines
options.general.color.descriptor.whitespaces.modified.lines=Editor Gutter//Whitespace-modified lines
options.general.color.descriptor.border.lines=Editor Gutter//Border
options.general.color.descriptor.console.background=Console//Background
options.general.color.descriptor.console.stdout=Console//Standard output
options.general.color.descriptor.console.stderr=Console//Error output
@@ -53,6 +53,12 @@
<option name="FILESTATUS_OBSOLETE" value="7c7c00"/>
<option name="FILESTATUS_SWITCHED" value="08978f"/>
<option name="FILESTATUS_SUPPRESSED" value=""/>
<option name="VCS_ANNOTATIONS_COLOR_1" value="eaffe2"/>
<option name="VCS_ANNOTATIONS_COLOR_2" value="d1d1d1"/>
<option name="VCS_ANNOTATIONS_COLOR_3" value="d9e4f9"/>
<option name="VCS_ANNOTATIONS_COLOR_4" value="fffbcf"/>
<option name="VCS_ANNOTATIONS_COLOR_5" value="ffbfc3"/>
</colors>
<attributes>
@@ -1049,6 +1055,12 @@
<option name="DIFF_SEPARATORS_TOP_BORDER" value="1E1E1E"/>
<option name="DIFF_SEPARATORS_BACKGROUND" value="232323"/>
<option name="DIFF_SEPARATORS_BOTTOM_BORDER" value="222222"/>
<option name="VCS_ANNOTATIONS_COLOR_1" value="464c43"/>
<option name="VCS_ANNOTATIONS_COLOR_2" value="444342"/>
<option name="VCS_ANNOTATIONS_COLOR_3" value="41444a"/>
<option name="VCS_ANNOTATIONS_COLOR_4" value="484248"/>
<option name="VCS_ANNOTATIONS_COLOR_5" value="4c393a"/>
</colors>
<attributes>
<option name="ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES">
@@ -5,6 +5,8 @@
<applicationService serviceInterface="com.intellij.codeInsight.actions.FormatChangedTextUtil"
serviceImplementation="com.intellij.codeInsight.actions.VcsAwareFormatChangedTextUtil" overrides="true"/>
<applicationService serviceInterface="com.intellij.openapi.vcs.actions.AnnotationsSettings"
serviceImplementation="com.intellij.openapi.vcs.actions.AnnotationsSettings"/>
<projectService serviceInterface="com.intellij.openapi.vcs.AbstractVcsHelper"
serviceImplementation="com.intellij.openapi.vcs.impl.AbstractVcsHelperImpl"/>
@@ -33,6 +35,8 @@
<search.topHitProvider implementation="com.intellij.openapi.vcs.configurable.VcsOptionsTopHitProvider"/>
<projectConfigurable groupId="root" groupWeight="45" dynamic="true" key="version.control.main.configurable.name" bundle="messages.VcsBundle"
provider="com.intellij.openapi.vcs.configurable.VcsManagerConfigurableProvider" id="project.propVCSSupport.Mappings"/>
<colorAndFontPanelFactory implementation="com.intellij.openapi.vcs.actions.VcsColorsPageFactory"/>
<colorAndFontDescriptorProvider implementation="com.intellij.openapi.vcs.actions.VcsColorsPageFactory"/>
<changesViewContent tabName="Repository" className="com.intellij.openapi.vcs.changes.committed.CommittedChangesViewManager"
predicateClassName="com.intellij.openapi.vcs.changes.committed.CommittedChangesVisibilityPredicate"/>
@@ -19,6 +19,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.localVcs.UpToDateLineNumberProvider;
@@ -50,7 +51,7 @@ import java.util.Map;
* @author Konstantin Bulenkov
* @author: lesya
*/
public class AnnotateToggleAction extends ToggleAction implements DumbAware, AnnotationColors {
public class AnnotateToggleAction extends ToggleAction implements DumbAware {
public static final ExtensionPointName<Provider> EP_NAME =
ExtensionPointName.create("com.intellij.openapi.vcs.actions.AnnotateToggleAction.Provider");
@@ -121,7 +122,7 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann
presentation.addAction(Separator.getInstance());
final Couple<Map<VcsRevisionNumber, Color>> bgColorMap =
Registry.is("vcs.show.colored.annotations") ? computeBgColors(fileAnnotation) : null;
Registry.is("vcs.show.colored.annotations") ? computeBgColors(fileAnnotation, editor) : null;
final Map<VcsRevisionNumber, Integer> historyIds = Registry.is("vcs.show.history.numbers") ? computeLineNumbers(fileAnnotation) : null;
if (switcher != null) {
@@ -200,13 +201,16 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann
}
@NotNull
private static Couple<Map<VcsRevisionNumber, Color>> computeBgColors(@NotNull FileAnnotation fileAnnotation) {
private static Couple<Map<VcsRevisionNumber, Color>> computeBgColors(@NotNull FileAnnotation fileAnnotation, @NotNull Editor editor) {
final Map<VcsRevisionNumber, Color> commitOrderColors = new HashMap<VcsRevisionNumber, Color>();
final Map<VcsRevisionNumber, Color> commitAuthorColors = new HashMap<VcsRevisionNumber, Color>();
final Map<String, Color> authorColors = new HashMap<String, Color>();
final List<VcsFileRevision> fileRevisionList = fileAnnotation.getRevisions();
if (fileRevisionList != null) {
final int colorsCount = BG_COLORS.length;
EditorColorsScheme colorScheme = editor.getColorsScheme();
AnnotationsSettings settings = AnnotationsSettings.getInstance();
List<Color> authorsColorPalette = settings.getAuthorsColors(colorScheme);
List<Color> orderedColorPalette = settings.getOrderedColors(colorScheme);
final int revisionsCount = fileRevisionList.size();
for (int i = 0; i < fileRevisionList.size(); i++) {
@@ -218,14 +222,14 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware, Ann
if (!commitAuthorColors.containsKey(number)) {
if (author != null && !authorColors.containsKey(author)) {
final int index = authorColors.size();
Color color = BG_COLORS[index * BG_COLORS_PRIME % colorsCount];
Color color = authorsColorPalette.get(index % authorsColorPalette.size());
authorColors.put(author, color);
}
commitAuthorColors.put(number, authorColors.get(author));
}
if (!commitOrderColors.containsKey(number)) {
Color color = BG_COLORS[colorsCount * i / revisionsCount];
Color color = orderedColorPalette.get(orderedColorPalette.size() * i / revisionsCount);
commitOrderColors.put(number, color);
}
}
@@ -15,31 +15,16 @@
*/
package com.intellij.openapi.vcs.actions;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.util.ArrayUtil;
import java.awt.*;
/**
* @author Konstantin Bulenkov
* @deprecated use {@link AnnotationsSettings} instead
*/
@Deprecated
public interface AnnotationColors {
int BG_COLORS_PRIME = 3;
Color[] BG_COLORS = {
new JBColor(new Color(234, 255, 226), new Color(70, 76, 67)),
new JBColor(new Color(222, 241, 229), new Color(66, 72, 68)),
new JBColor(new Color(208, 229, 229), new Color(62, 68, 68)),
new JBColor(new Color(227, 226, 223), new Color(68, 67, 66)),
new JBColor(Gray._236, Gray._70),
new JBColor(new Color(217, 222, 229), new Color(65, 66, 68)),
new JBColor(new Color(217, 228, 249), new Color(65, 68, 74)),
new JBColor(new Color(220, 204, 236), new Color(66, 61, 70)),
new JBColor(new Color(255, 204, 238), new Color(76, 61, 71)),
new JBColor(new Color(243, 223, 243), new Color(72, 66, 72)),
new JBColor(new Color(255, 251, 207), new Color(76, 75, 62)),
new JBColor(new Color(255, 226, 199), new Color(76, 67, 59)),
new JBColor(new Color(255, 213, 203), new Color(76, 63, 60)),
new JBColor(new Color(255, 191, 195), new Color(76, 57, 58)),
};
Color[] BG_COLORS = ArrayUtil.toObjectArray(AnnotationsSettings.getInstance().getOrderedColors(null), Color.class);
}
@@ -0,0 +1,77 @@
/*
* Copyright 2000-2010 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.vcs.actions;
import com.intellij.openapi.components.ServiceManager;
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.vcs.ui.ColorGenerator;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class AnnotationsSettings {
static final List<ColorKey> ANCHOR_COLOR_KEYS = createColorKeys(5);
static final int COLOR_COUNT = 20;
private static final int SHUFFLE_STEP = 4;
@NotNull
private static List<ColorKey> createColorKeys(int count) {
List<ColorKey> keys = new ArrayList<>();
for (int i = 0; i < count; i++) {
keys.add(ColorKey.createColorKey("VCS_ANNOTATIONS_COLOR_" + (i + 1)));
}
return keys;
}
public static AnnotationsSettings getInstance() {
return ServiceManager.getService(AnnotationsSettings.class);
}
@NotNull
public List<Color> getAuthorsColors(@Nullable EditorColorsScheme scheme) {
if (scheme == null) scheme = EditorColorsManager.getInstance().getGlobalScheme();
List<Color> colors = getOrderedColors(scheme);
List<Color> authorColors = new ArrayList<>();
for (int i = 0; i < SHUFFLE_STEP; i++) {
for (int k = 0; k <= colors.size() / SHUFFLE_STEP; k++) {
int index = k * SHUFFLE_STEP + i;
if (index < colors.size()) authorColors.add(colors.get(index));
}
}
return authorColors;
}
@NotNull
public List<Color> getOrderedColors(@Nullable EditorColorsScheme scheme) {
if (scheme == null) scheme = EditorColorsManager.getInstance().getGlobalScheme();
List<Color> anchorColors = new ArrayList<>();
for (ColorKey key : ANCHOR_COLOR_KEYS) {
ContainerUtil.addIfNotNull(anchorColors, scheme.getColor(key));
}
return ColorGenerator.generateLinearColorSequence(anchorColors, COLOR_COUNT);
}
}
@@ -0,0 +1,99 @@
/*
* 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.vcs.actions;
import com.intellij.application.options.colors.*;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.options.OptionsBundle;
import com.intellij.openapi.options.colors.AttributesDescriptor;
import com.intellij.openapi.options.colors.ColorAndFontDescriptorsProvider;
import com.intellij.openapi.options.colors.ColorDescriptor;
import com.intellij.psi.codeStyle.DisplayPriority;
import com.intellij.psi.codeStyle.DisplayPrioritySortable;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class VcsColorsPageFactory implements ColorAndFontPanelFactory, ColorAndFontDescriptorsProvider, DisplayPrioritySortable {
public static final String VCS_GROUP = ApplicationBundle.message("title.vcs");
@Override
@NotNull
public NewColorAndFontPanel createPanel(@NotNull ColorAndFontOptions options) {
final SchemesPanel schemesPanel = new SchemesPanel(options);
final OptionsPanelImpl optionsPanel = new OptionsPanelImpl(options, schemesPanel, VCS_GROUP);
final VcsPreviewPanel previewPanel = new VcsPreviewPanel();
schemesPanel.addListener(new ColorAndFontSettingsListener.Abstract() {
@Override
public void schemeChanged(final Object source) {
previewPanel.setColorScheme(options.getSelectedScheme());
optionsPanel.updateOptionsList();
}
});
return new NewColorAndFontPanel(schemesPanel, optionsPanel, previewPanel, VCS_GROUP, null, null);
}
@Override
@NotNull
public AttributesDescriptor[] getAttributeDescriptors() {
return new AttributesDescriptor[0];
}
@Override
@NotNull
public ColorDescriptor[] getColorDescriptors() {
List<ColorDescriptor> descriptors = new ArrayList<>();
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.added.lines"), EditorColors.ADDED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.modified.lines"), EditorColors.MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.deleted.lines"), EditorColors.DELETED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.whitespaces.modified.lines"), EditorColors.WHITESPACES_MODIFIED_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.border.lines"), EditorColors.BORDER_LINES_COLOR, ColorDescriptor.Kind.BACKGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations"), EditorColors.ANNOTATIONS_COLOR, ColorDescriptor.Kind.FOREGROUND));
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations.merged"), EditorColors.ANNOTATIONS_MERGED_COLOR, ColorDescriptor.Kind.FOREGROUND));
List<ColorKey> colorKeys = AnnotationsSettings.ANCHOR_COLOR_KEYS;
for (int i = 0; i < colorKeys.size(); i++) {
descriptors.add(new ColorDescriptor(OptionsBundle.message("options.general.color.descriptor.vcs.annotations.color.n", i + 1), colorKeys.get(i), ColorDescriptor.Kind.BACKGROUND));
}
return ArrayUtil.toObjectArray(descriptors, ColorDescriptor.class);
}
@NotNull
@Override
public String getPanelDisplayName() {
return VCS_GROUP;
}
@Override
@NotNull
public String getDisplayName() {
return VCS_GROUP;
}
@Override
public DisplayPriority getPriority() {
return DisplayPriority.COMMON_SETTINGS;
}
}
@@ -0,0 +1,200 @@
/*
* 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.vcs.actions;
import com.intellij.application.options.colors.ColorAndFontSettingsListener;
import com.intellij.application.options.colors.PreviewPanel;
import com.intellij.diff.util.DiffUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.TextAnnotationGutterProvider;
import com.intellij.openapi.editor.colors.ColorKey;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.ex.LineStatusMarkerRenderer;
import com.intellij.openapi.vcs.ex.Range;
import com.intellij.openapi.vcs.ex.Range.InnerRange;
import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class VcsPreviewPanel implements PreviewPanel {
private final EventDispatcher<ColorAndFontSettingsListener> myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class);
private final EditorEx myEditor;
public VcsPreviewPanel() {
StringBuilder sb = new StringBuilder();
sb.append(
"Deleted line below\n\n" +
"Modified line\n\n" +
"Added line\n\n" +
"Line with modified whitespaces\n\n" +
"Added line\n" +
"Line with modified whitespaces and deletion after\n"
);
int additionalLines = Math.max(0, AnnotationsSettings.COLOR_COUNT - StringUtil.countNewLines(sb));
sb.append(StringUtil.repeat("\n", additionalLines));
DocumentImpl document = new DocumentImpl(sb);
myEditor = (EditorEx)EditorFactory.getInstance().createViewer(document);
}
@Override
public void disposeUIResources() {
EditorFactory.getInstance().releaseEditor(myEditor);
}
@Override
public Component getPanel() {
return myEditor.getComponent();
}
@Override
public void blinkSelectedHighlightType(Object selected) {
}
@Override
public void updateView() {
myEditor.getMarkupModel().removeAllHighlighters();
myEditor.getGutterComponentEx().closeAllAnnotations();
addHighlighter(new Range(1, 1, 0, 1), EditorColors.DELETED_LINES_COLOR);
addHighlighter(createModifiedRange(2, Range.MODIFIED), EditorColors.MODIFIED_LINES_COLOR);
addHighlighter(createModifiedRange(4, Range.INSERTED), EditorColors.ADDED_LINES_COLOR);
addHighlighter(createModifiedRange(6, Range.EQUAL), EditorColors.WHITESPACES_MODIFIED_LINES_COLOR);
addHighlighter(createModifiedRange(8, Range.INSERTED, Range.EQUAL, Range.DELETED), EditorColors.WHITESPACES_MODIFIED_LINES_COLOR);
List<Color> annotationColors = AnnotationsSettings.getInstance().getOrderedColors(myEditor.getColorsScheme());
myEditor.getGutterComponentEx().registerTextAnnotation(new MyTextAnnotationGutterProvider(annotationColors));
}
@NotNull
private static Range createModifiedRange(int currentLine, byte... inner) {
List<InnerRange> innerRanges = new ArrayList<>();
int currentInnerLine = currentLine;
for (byte type : inner) {
switch (type) {
case Range.EQUAL:
case Range.INSERTED:
case Range.MODIFIED:
innerRanges.add(new InnerRange(currentInnerLine, currentInnerLine + 1, type));
currentInnerLine++;
break;
case Range.DELETED:
innerRanges.add(new InnerRange(currentInnerLine, currentInnerLine, type));
break;
}
}
return new Range(currentLine, currentInnerLine, 0, 1, innerRanges);
}
private void addHighlighter(@NotNull Range range, @NotNull ColorKey colorKey) {
TextRange textRange = DiffUtil.getLinesRange(myEditor.getDocument(), range.getLine1(), range.getLine2());
RangeHighlighter highlighter = LineStatusMarkerRenderer.createRangeHighlighter(range, textRange, myEditor.getMarkupModel());
highlighter.setLineMarkerRenderer(new LineStatusMarkerRenderer(range) {
@Override
public void doAction(Editor editor, MouseEvent e) {
myDispatcher.getMulticaster().selectionInPreviewChanged(colorKey.getExternalName());
}
});
}
@Override
public void addListener(@NotNull ColorAndFontSettingsListener listener) {
myDispatcher.addListener(listener);
}
public void setColorScheme(final EditorColorsScheme highlighterSettings) {
myEditor.setColorsScheme(highlighterSettings);
}
private static class MyTextAnnotationGutterProvider implements TextAnnotationGutterProvider {
@NotNull private final List<Color> myBackgroundColors;
public MyTextAnnotationGutterProvider(@NotNull List<Color> backgroundColors) {
myBackgroundColors = backgroundColors;
}
@Nullable
@Override
public String getLineText(int line, Editor editor) {
if (line == 0) return "Merged commit (SVN)";
int colorNumber = line - 1;
if (colorNumber < myBackgroundColors.size()) {
return "Annotation background #" + (colorNumber + 1);
}
return null;
}
@Nullable
@Override
public String getToolTip(int line, Editor editor) {
return null;
}
@Override
public EditorFontType getStyle(int line, Editor editor) {
return null;
}
@Nullable
@Override
public ColorKey getColor(int line, Editor editor) {
if (line == 0) return EditorColors.ANNOTATIONS_MERGED_COLOR;
return EditorColors.ANNOTATIONS_COLOR;
}
@Nullable
@Override
public Color getBgColor(int line, Editor editor) {
if (line == 0) return myBackgroundColors.get(0);
int colorNumber = line - 1;
if (colorNumber < myBackgroundColors.size()) {
return myBackgroundColors.get(colorNumber);
}
return null;
}
@Override
public List<AnAction> getPopupActions(int line, Editor editor) {
return Collections.emptyList();
}
@Override
public void gutterClosed() {
}
}
}
@@ -0,0 +1,77 @@
/*
* 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.vcs.ui;
import com.intellij.ui.JBColor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ColorGenerator {
@NotNull
public static List<Color> generateLinearColorSequence(@NotNull List<Color> anchorColors, int count) {
if (count == 0) return Collections.emptyList();
if (anchorColors.isEmpty()) return Collections.nCopies(count, JBColor.GRAY);
if (anchorColors.size() == 1) return Collections.nCopies(count, anchorColors.get(0));
List<Color> result = new ArrayList<>();
result.add(anchorColors.get(0));
int segmentCount = anchorColors.size() - 1;
int colorPerSegment = (count - 1) / segmentCount;
if (count - 1 > colorPerSegment * segmentCount) colorPerSegment++; // divide rounding up
for (int i = 0; i < segmentCount; i++) {
Color color1 = anchorColors.get(i);
Color color2 = anchorColors.get(i + 1);
List<Color> linearColors = generateLinearColorSequence(color1, color2, colorPerSegment + 1);
// skip first element from sequence to avoid duplication from connected segments
result.addAll(linearColors.subList(1, linearColors.size()));
}
return result.subList(0, count);
}
@NotNull
public static List<Color> generateLinearColorSequence(@NotNull Color color1, @NotNull Color color2, int count) {
if (count == 1) return ContainerUtil.list(color1);
if (count == 2) return ContainerUtil.list(color1, color2);
List<Color> result = new ArrayList<>();
for (int i = 0; i < count; i++) {
float ratio = (float)i / (count - 1);
//noinspection UseJBColor
result.add(new Color(
ratio(color1.getRed(), color2.getRed(), ratio),
ratio(color1.getGreen(), color2.getGreen(), ratio),
ratio(color1.getBlue(), color2.getBlue(), ratio)
));
}
return result;
}
private static int ratio(int val1, int val2, float ratio) {
int value = (int)(val1 + ((val2 - val1) * ratio));
return Math.max(Math.min(value, 255), 0);
}
}
@@ -0,0 +1,61 @@
/*
* 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.vcs.ui
import com.intellij.testFramework.UsefulTestCase
import com.intellij.ui.Gray
import java.awt.Color
class ColorGeneratorTest : UsefulTestCase () {
fun testLineGeneration() {
for (count in 0..5) {
assertEquals(count, generate(Color.BLACK, Color.WHITE, count).size)
}
assertOrderedEquals(generate(Gray._100, Gray._200, 1), listOf(Gray._100))
assertOrderedEquals(generate(Gray._100, Gray._200, 2), listOf(Gray._100, Gray._200))
assertOrderedEquals(generate(Gray._100, Gray._200, 3), listOf(Gray._100, Gray._150, Gray._200))
assertOrderedEquals(generate(Gray._100, Gray._200, 5), listOf(Gray._100, Gray._125, Gray._150, Gray._175, Gray._200))
assertOrderedEquals(generate(Color(0, 100, 200), Color(200, 100, 0), 3), listOf(Color(0, 100, 200), Color(100, 100, 100), Color(200, 100, 0)))
}
fun testChainLineGeneration() {
for (anchorCount in 0..5) {
val anchors = generate(Color.BLACK, Color.WHITE, anchorCount)
for (count in 0..40) {
val generated = generateChain(count, anchors)
assertEquals(count, generated.size)
}
}
assertOrderedEquals(generateChain(1, Gray._100, Gray._200), listOf(Gray._100))
assertOrderedEquals(generateChain(2, Gray._100, Gray._200), listOf(Gray._100, Gray._200))
assertOrderedEquals(generateChain(3, Gray._100, Gray._200), listOf(Gray._100, Gray._150, Gray._200))
assertOrderedEquals(generateChain(5, Gray._100, Gray._200), listOf(Gray._100, Gray._125, Gray._150, Gray._175, Gray._200))
assertOrderedEquals(generateChain(3, Gray._0, Gray._100, Gray._200), listOf(Gray._0, Gray._100, Gray._200))
assertOrderedEquals(generateChain(5, Gray._0, Gray._100, Gray._200), listOf(Gray._0, Gray._50, Gray._100, Gray._150, Gray._200))
assertOrderedEquals(generateChain(9, Gray._0, Gray._100, Gray._200), listOf(Gray._0, Gray._25, Gray._50, Gray._75, Gray._100, Gray._125, Gray._150, Gray._175, Gray._200))
assertOrderedEquals(generateChain(3, Color(0, 100, 200), Color(200, 100, 0)), listOf(Color(0, 100, 200), Color(100, 100, 100), Color(200, 100, 0)))
assertOrderedEquals(generateChain(5, Color(0, 100, 200), Color(0, 0, 0), Color(200, 100, 0)), listOf(Color(0, 100, 200), Color(0, 50, 100), Color(0, 0, 0), Color(100, 50, 0), Color(200, 100, 0)))
}
fun generate(color1: Color, color2: Color, count: Int) = ColorGenerator.generateLinearColorSequence(color1, color2, count)
fun generateChain(count: Int, vararg colors: Color) = ColorGenerator.generateLinearColorSequence(colors.asList(), count)
fun generateChain(count: Int, colors: List<Color>) = ColorGenerator.generateLinearColorSequence(colors, count)
}