mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[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:
+37
-10
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user