[diff] Draw highlighters above gutters. Step 5: fix line render for soft-wrapped inline fragments

PROBLEM:
inline fragment can appear on 2 visible soft-wrapped lines (in case of short diff, for example), but we draw them only on one.

SOLUTION:
Make DiffLineMarkerRenderer calculate the real visual height of the modified range and draw the rectangle with correct height.
This commit is contained in:
Kirill Likhodedov
2012-10-31 15:06:58 +04:00
parent 3b5e949038
commit 15efbf2b12
3 changed files with 43 additions and 14 deletions
@@ -20,8 +20,10 @@ 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.*;
@@ -30,18 +32,29 @@ import java.awt.*;
* <p>Has ability to draw applied changes (used in the merge tool).</p>
*/
public class DiffLineMarkerRenderer implements LineMarkerRenderer {
private final TextDiffType myDiffType;
private final boolean myEnsureAtLeastOneLineHigh;
@NotNull private final TextDiffType myDiffType;
@Nullable private final TextRange myTextRange;
@NotNull
public static DiffLineMarkerRenderer createStandardInstance(@NotNull TextDiffType diffType) {
return new DiffLineMarkerRenderer(diffType, null);
}
/**
* @param diffType the type of the difference.
* @param ensureAtLeastOneLineHigh if true, the height of the rectangle will be at least one line high,
* if 0 is passed as a height of the Rectangle to {@link #paint(Editor, Graphics, Rectangle)}.
* The height won't be modified if ensureAtLeastOneLineHigh is false, or if height is not 0.
* 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.
*/
public DiffLineMarkerRenderer(@NotNull TextDiffType diffType, boolean ensureAtLeastOneLineHigh) {
@NotNull
public static DiffLineMarkerRenderer createHeightAdjustingInstance(@NotNull TextDiffType diffType, @NotNull TextRange range) {
return new DiffLineMarkerRenderer(diffType, range);
}
private DiffLineMarkerRenderer(@NotNull TextDiffType diffType, @Nullable TextRange range) {
myDiffType = diffType;
myEnsureAtLeastOneLineHigh = ensureAtLeastOneLineHigh;
myTextRange = range;
}
@Override
@@ -58,8 +71,8 @@ public class DiffLineMarkerRenderer implements LineMarkerRenderer {
int width = gutter.getWidth();
int height = range.height;
if (height == 0 && myEnsureAtLeastOneLineHigh) {
height = editor.getLineHeight();
if (myTextRange != null) {
height = calcHeightInVisualLines(editor, myTextRange) * editor.getLineHeight();
}
if (!myDiffType.isApplied()) {
@@ -77,4 +90,18 @@ public class DiffLineMarkerRenderer implements LineMarkerRenderer {
DiffUtil.drawBoldDottedFramingLines(g2, x, x + width, y - 1, y + height - 1, color);
}
}
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;
}
}
@@ -95,8 +95,10 @@ public abstract class DiffMarkup implements EditorSource, Disposable {
rangeMarker.setGutterIconRenderer(gutterIconRenderer);
}
boolean ensureAtLeastOneLineHigh = shouldIncreaseHighlightingHeight(fragment, editor, range);
rangeMarker.setLineMarkerRenderer(new DiffLineMarkerRenderer(type, ensureAtLeastOneLineHigh));
boolean adjustHeight = shouldIncreaseHighlightingHeight(fragment, editor, range);
rangeMarker.setLineMarkerRenderer(adjustHeight
? DiffLineMarkerRenderer.createHeightAdjustingInstance(type, range)
: DiffLineMarkerRenderer.createStandardInstance(type));
Color stripeBarColor = attributes.getErrorStripeColor();
if (stripeBarColor != null) {
@@ -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(new DiffLineMarkerRenderer(diffType, false));
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createStandardInstance(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(new DiffLineMarkerRenderer(type, false));
highlighter.setLineMarkerRenderer(DiffLineMarkerRenderer.createStandardInstance(type));
return highlighter;
}