From 15efbf2b1208761a28fc084e7aa4da878c28287d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 11 Sep 2012 12:35:41 +0400 Subject: [PATCH] [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. --- .../diff/impl/DiffLineMarkerRenderer.java | 47 +++++++++++++++---- .../diff/impl/highlighting/DiffMarkup.java | 6 ++- .../ChangeHighlighterHolder.java | 4 +- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffLineMarkerRenderer.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffLineMarkerRenderer.java index 86cf702f5559..8a7e01e03f57 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffLineMarkerRenderer.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffLineMarkerRenderer.java @@ -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.*; *

Has ability to draw applied changes (used in the merge tool).

*/ 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; + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/DiffMarkup.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/DiffMarkup.java index 7347f82e4c04..29f0c32439e0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/DiffMarkup.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/highlighting/DiffMarkup.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java index ac81a93025e1..89a1f3dcf568 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ChangeHighlighterHolder.java @@ -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; }