[diff] Highlight the whole line for inline fragment, but with less intensive color.

* Don't highlight the line marker renderer for inline changes - the line fragment wrapping them will be used.
* Therefore remove the code for adjusting text range height from the DiffLineMarkerRenderer.
* Introduce TextDiffType#myInlineWrapper for diff type of a fragment that is a wrapper for inline changes.
 - use special background color for such type.
 - refactor getTextAttributes: for scheme just return the color from scheme, all adjustments (for applied and for inline changes) are made in getTextAttributes(Editor).
* Create special inline TextDiffType instance where needed: in the LineBlocks (for DividerPolygons) and in the DiffMarkup (for the gutter and code highlighting).
This commit is contained in:
Kirill Likhodedov
2012-10-31 15:07:00 +04:00
parent be0f6c5513
commit 7af486c6cd
7 changed files with 101 additions and 68 deletions
@@ -20,10 +20,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.markup.LineMarkerRenderer;
import com.intellij.openapi.util.TextRange;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -34,27 +32,14 @@ import java.awt.*;
public class DiffLineMarkerRenderer implements LineMarkerRenderer {
@NotNull private final TextDiffType myDiffType;
@Nullable private final TextRange myTextRange;
@NotNull
public static DiffLineMarkerRenderer createStandardInstance(@NotNull TextDiffType diffType) {
return new DiffLineMarkerRenderer(diffType, null);
public static DiffLineMarkerRenderer createInstance(@NotNull TextDiffType diffType) {
return new DiffLineMarkerRenderer(diffType);
}
/**
* Creates an instance of the renderer that calculates the visual height of the text range and ensures that the drawn rectangle is at
* least as high as needed.
* @param diffType the type of the difference.
* @param range the highlighted text range.
*/
@NotNull
public static DiffLineMarkerRenderer createHeightAdjustingInstance(@NotNull TextDiffType diffType, @NotNull TextRange range) {
return new DiffLineMarkerRenderer(diffType, range);
}
private DiffLineMarkerRenderer(@NotNull TextDiffType diffType, @Nullable TextRange range) {
private DiffLineMarkerRenderer(@NotNull TextDiffType diffType) {
myDiffType = diffType;
myTextRange = range;
}
@Override
@@ -71,10 +56,6 @@ public class DiffLineMarkerRenderer implements LineMarkerRenderer {
int width = gutter.getWidth();
int height = range.height;
if (myTextRange != null) {
height = calcHeightInVisualLines(editor, myTextRange) * editor.getLineHeight();
}
if (!myDiffType.isApplied()) {
if (height > 2) {
g.setColor(color);
@@ -91,17 +72,4 @@ public class DiffLineMarkerRenderer implements LineMarkerRenderer {
}
}
private static int calcHeightInVisualLines(@NotNull Editor editor, @NotNull TextRange range) {
int startY = editor.offsetToVisualPosition(range.getStartOffset()).getLine();
int endY = editor.offsetToVisualPosition(range.getEndOffset()).getLine();
if (startY > endY) {
return 0;
}
return endY - startY + 1;
}
@NotNull
public TextDiffType getType() {
return myDiffType;
}
}
@@ -22,7 +22,9 @@ import com.intellij.openapi.diff.DiffViewer;
import com.intellij.openapi.diff.LineTokenizer;
import com.intellij.openapi.diff.ex.DiffFragment;
import com.intellij.openapi.diff.impl.external.DiffManagerImpl;
import com.intellij.openapi.diff.impl.fragments.LineFragment;
import com.intellij.openapi.diff.impl.util.FocusDiffSide;
import com.intellij.openapi.diff.impl.util.TextDiffType;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.EditorEx;
@@ -111,4 +113,12 @@ public class DiffUtil {
return backgroundColor.darker();
}
@NotNull
public static TextDiffType makeTextDiffType(@NotNull LineFragment fragment) {
TextDiffType type = TextDiffType.create(fragment.getType());
if (fragment.getChildrenIterator() != null) {
return TextDiffType.deriveInstanceForInlineWrapperFragment(type);
}
return type;
}
}
@@ -49,6 +49,8 @@ public class FragmentHighlighterImpl implements FragmentHighlighter {
}
public void highlightLine(final LineFragment fragment) {
highlightFragmentImpl(fragment);
addModifyActions(fragment, myAppender1, myAppender2);
final Iterator<Fragment> iterator = fragment.getChildrenIterator();
if (iterator == null) {
@@ -21,9 +21,11 @@ import com.intellij.openapi.diff.DiffColors;
import com.intellij.openapi.diff.actions.MergeActionGroup;
import com.intellij.openapi.diff.actions.MergeOperations;
import com.intellij.openapi.diff.impl.DiffLineMarkerRenderer;
import com.intellij.openapi.diff.impl.DiffUtil;
import com.intellij.openapi.diff.impl.EditorSource;
import com.intellij.openapi.diff.impl.fragments.Fragment;
import com.intellij.openapi.diff.impl.fragments.InlineFragment;
import com.intellij.openapi.diff.impl.fragments.LineFragment;
import com.intellij.openapi.diff.impl.util.GutterActionRenderer;
import com.intellij.openapi.diff.impl.util.TextDiffType;
import com.intellij.openapi.diff.impl.util.TextDiffTypeEnum;
@@ -69,14 +71,16 @@ public abstract class DiffMarkup implements EditorSource, Disposable {
public void highlightText(@NotNull Fragment fragment, @Nullable GutterIconRenderer gutterIconRenderer) {
MarkupModel markupModel = getMarkupModel();
Editor editor = getEditor();
EditorEx editor = getEditor();
TextDiffTypeEnum diffTypeEnum = fragment.getType();
if (diffTypeEnum == null || markupModel == null || editor == null) {
return;
}
TextDiffType type = TextDiffType.create(diffTypeEnum);
TextDiffType type = fragment instanceof LineFragment
? DiffUtil.makeTextDiffType((LineFragment)fragment)
: TextDiffType.create(diffTypeEnum);
TextRange range = fragment.getRange(getSide());
TextAttributes attributes = type.getTextAttributes(getEditor());
TextAttributes attributes = type.getTextAttributes(editor);
if (attributes == null) {
return;
}
@@ -95,23 +99,18 @@ public abstract class DiffMarkup implements EditorSource, Disposable {
rangeMarker.setGutterIconRenderer(gutterIconRenderer);
}
boolean adjustHeight = shouldIncreaseHighlightingHeight(fragment);
rangeMarker.setLineMarkerRenderer(adjustHeight
? DiffLineMarkerRenderer.createHeightAdjustingInstance(type, range)
: DiffLineMarkerRenderer.createStandardInstance(type));
if (!(fragment instanceof InlineFragment)) {
rangeMarker.setLineMarkerRenderer(DiffLineMarkerRenderer.createInstance(type));
Color stripeBarColor = attributes.getErrorStripeColor();
if (stripeBarColor != null) {
rangeMarker.setErrorStripeMarkColor(stripeBarColor);
rangeMarker.setThinErrorStripeMark(true);
Color stripeBarColor = attributes.getErrorStripeColor();
if (stripeBarColor != null) {
rangeMarker.setErrorStripeMarkColor(stripeBarColor);
rangeMarker.setThinErrorStripeMark(true);
}
}
saveHighlighter(rangeMarker);
}
private static boolean shouldIncreaseHighlightingHeight(@NotNull Fragment fragment) {
return fragment instanceof InlineFragment;
}
public void addLineMarker(int line, @Nullable TextAttributesKey type) {
RangeHighlighter marker = createLineMarker(type, line);
if (marker == null) return;
@@ -78,7 +78,7 @@ class ChangeHighlighterHolder {
RangeHighlighter highlighter = getMarkupModel().addLineHighlighter(line, layer, null);
highlighter.setLineSeparatorColor(diffType.getTextBackground(myEditor));
highlighterCreated(highlighter, diffType.getTextAttributes(myEditor), applied);
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createStandardInstance(diffType));
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createInstance(diffType));
return highlighter;
}
@@ -89,7 +89,7 @@ class ChangeHighlighterHolder {
TextAttributes attributes = type.getTextAttributes(myEditor);
RangeHighlighter highlighter = getMarkupModel().addRangeHighlighter(start, end, layer, attributes, targetArea);
highlighterCreated(highlighter, attributes, applied);
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createStandardInstance(type));
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createInstance(type));
return highlighter;
}
@@ -16,6 +16,7 @@
package com.intellij.openapi.diff.impl.splitter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.impl.DiffUtil;
import com.intellij.openapi.diff.impl.fragments.LineBlock;
import com.intellij.openapi.diff.impl.fragments.LineFragment;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
@@ -178,11 +179,19 @@ public class LineBlocks {
for (LineBlock block : blocks) {
Interval interval1 = new Interval(block.getStartingLine1(), block.getModifiedLines1());
Interval interval2 = new Interval(block.getStartingLine2(), block.getModifiedLines2());
diffs.add(new Diff(interval1, interval2, TextDiffType.create(block.getType())));
diffs.add(new Diff(interval1, interval2, makeTextDiffType(block)));
}
return new LineBlocks(diffs);
}
private static TextDiffType makeTextDiffType(LineBlock block) {
TextDiffType type = TextDiffType.create(block.getType());
if (block instanceof LineFragment) {
return DiffUtil.makeTextDiffType((LineFragment)block);
}
return type;
}
@NotNull
public static LineBlocks fromChanges(@NotNull List<Change> changes) {
// changes may come mixed, need to sort them to get correct intervals
@@ -21,6 +21,7 @@ import com.intellij.openapi.diff.ex.DiffStatusBar;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NotNull;
@@ -46,16 +47,22 @@ public class TextDiffType implements DiffStatusBar.LegendTypeDescriptor {
return textDiffType.getAttributesKey();
}
};
private static final double MIDDLE_COLOR_FACTOR = 0.6;
private final TextDiffTypeEnum myType;
private final TextAttributesKey myAttributesKey;
private final String myDisplayName;
private final boolean myApplied;
private final boolean myInlineWrapper;
public boolean isApplied() {
return myApplied;
}
public boolean isInlineWrapper() {
return myInlineWrapper;
}
@NotNull
public static TextDiffType create(@Nullable final TextDiffTypeEnum type) {
if (TextDiffTypeEnum.INSERT.equals(type)) {
@@ -78,18 +85,24 @@ public class TextDiffType implements DiffStatusBar.LegendTypeDescriptor {
*/
@NotNull
public static TextDiffType deriveApplied(@NotNull TextDiffType source) {
return new TextDiffType(source.myType, source.myDisplayName, source.myAttributesKey, true);
return new TextDiffType(source.myType, source.myDisplayName, source.myAttributesKey, true, false);
}
public static TextDiffType deriveInstanceForInlineWrapperFragment(@NotNull TextDiffType source) {
return new TextDiffType(source.myType, source.myDisplayName, source.myAttributesKey, source.myApplied, true);
}
private TextDiffType(TextDiffTypeEnum type, String displayName, TextAttributesKey attributesKey) {
this(type, displayName, attributesKey, false);
this(type, displayName, attributesKey, false, false);
}
private TextDiffType(TextDiffTypeEnum type, String displayName, TextAttributesKey attributesKey, boolean applied) {
private TextDiffType(TextDiffTypeEnum type, String displayName, TextAttributesKey attributesKey, boolean applied,
boolean inlineWrapper) {
myType = type;
myAttributesKey = attributesKey;
myDisplayName = displayName;
myApplied = applied;
myInlineWrapper = inlineWrapper;
}
public String getDisplayName() {
@@ -108,15 +121,7 @@ public class TextDiffType implements DiffStatusBar.LegendTypeDescriptor {
@Nullable
public TextAttributes getTextAttributes(EditorColorsScheme scheme) {
TextAttributes originalAttrs = scheme.getAttributes(myAttributesKey);
if (originalAttrs == null) {
return null;
}
TextAttributes overridingAttributes = new TextAttributes();
if (myApplied) {
overridingAttributes.setBackgroundColor(scheme.getDefaultBackground());
}
return TextAttributes.merge(originalAttrs, overridingAttributes);
return scheme.getAttributes(myAttributesKey);
}
@Nullable
@@ -124,15 +129,29 @@ public class TextDiffType implements DiffStatusBar.LegendTypeDescriptor {
if (isApplied()) {
return getLegendColor(editor.getColorsScheme());
}
else if (isInlineWrapper()) {
return getBgColorForFragmentContainingInlines((EditorEx)editor);
}
else {
TextAttributes attributes = getTextAttributes(editor.getColorsScheme());
TextAttributes attributes = getTextAttributes(editor);
return attributes == null ? null : attributes.getBackgroundColor();
}
}
@Nullable
public TextAttributes getTextAttributes(Editor editor) {
return getTextAttributes(editor.getColorsScheme());
public TextAttributes getTextAttributes(@NotNull Editor editor) {
TextAttributes originalAttrs = getTextAttributes(editor.getColorsScheme());
if (originalAttrs == null) {
return null;
}
TextAttributes overridingAttributes = new TextAttributes();
if (myApplied) {
overridingAttributes.setBackgroundColor(((EditorEx)editor).getBackgroundColor());
}
else if (myInlineWrapper) {
overridingAttributes.setBackgroundColor(getBgColorForFragmentContainingInlines((EditorEx)editor));
}
return TextAttributes.merge(originalAttrs, overridingAttributes);
}
@Nullable
@@ -149,4 +168,30 @@ public class TextDiffType implements DiffStatusBar.LegendTypeDescriptor {
return myType;
}
@Nullable
private Color getBgColorForFragmentContainingInlines(@NotNull EditorEx editor) {
TextAttributes originalAttrs = getTextAttributes(editor.getColorsScheme());
if (originalAttrs == null) {
return null;
}
Color fg = originalAttrs.getBackgroundColor();
if (fg == null) {
return null;
}
Color bg = editor.getBackgroundColor();
return getMiddleColor(fg, bg, MIDDLE_COLOR_FACTOR);
}
@NotNull
private static Color getMiddleColor(Color fg, Color bg, double factor) {
int red = avg(fg.getRed(), bg.getRed(), factor);
int green = avg(fg.getGreen(), bg.getGreen(), factor);
int blue = avg(fg.getBlue(), bg.getBlue(), factor);
return new Color(red, green, blue);
}
private static int avg(int fg, int bg, double factor) {
return (int)(fg + Math.round(factor * (bg - fg)));
}
}