diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java index 549255ce3f44..12b3b476df72 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffChange.java @@ -48,18 +48,18 @@ public class SimpleDiffChange { private int[] myLineStartShifts = new int[2]; private int[] myLineEndShifts = new int[2]; - // TODO: adjust color from inner fragments - configurable public SimpleDiffChange(@NotNull SimpleDiffViewer viewer, - @NotNull LineFragment fragment) { + @NotNull LineFragment fragment, + @Nullable LineFragment previousFragment) { myViewer = viewer; myFragment = fragment; myInnerFragments = fragment.getInnerFragments(); - installHighlighter(); + installHighlighter(previousFragment); } - public void installHighlighter() { + public void installHighlighter(@Nullable LineFragment previousFragment) { assert myHighlighters.isEmpty(); if (myInnerFragments != null) { @@ -68,6 +68,8 @@ public class SimpleDiffChange { else { doInstallHighlighterSimple(); } + doInstallNonSquashedChangesSeparator(previousFragment); + doInstallActionHighlighters(); } @@ -100,6 +102,11 @@ public class SimpleDiffChange { } } + private void doInstallNonSquashedChangesSeparator(@Nullable LineFragment previousFragment) { + createNonSquashedChangesSeparator(previousFragment, Side.LEFT); + createNonSquashedChangesSeparator(previousFragment, Side.RIGHT); + } + private void doInstallActionHighlighters() { myOperations.add(createOperation(Side.LEFT)); myOperations.add(createOperation(Side.RIGHT)); @@ -113,7 +120,6 @@ public class SimpleDiffChange { int endLine = side.getEndLine(myFragment); myHighlighters.addAll(DiffDrawUtil.createHighlighter(editor, startLine, endLine, type, ignored)); - myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, startLine, endLine, type, false)); } private void createInlineHighlighter(@NotNull DiffFragment fragment, @NotNull Side side) { @@ -129,6 +135,22 @@ public class SimpleDiffChange { myHighlighters.addAll(DiffDrawUtil.createInlineHighlighter(editor, start, end, type)); } + private void createNonSquashedChangesSeparator(@Nullable LineFragment previousFragment, @NotNull Side side) { + if (previousFragment == null) return; + + int startLine = side.getStartLine(myFragment); + int endLine = side.getEndLine(myFragment); + + int prevStartLine = side.getStartLine(previousFragment); + int prevEndLine = side.getEndLine(previousFragment); + + if (startLine == endLine) return; + if (prevStartLine == prevEndLine) return; + if (prevEndLine != startLine) return; + + myHighlighters.addAll(DiffDrawUtil.createLineMarker(myViewer.getEditor(side), startLine, TextDiffType.MODIFIED)); + } + public void updateGutterActions(boolean force) { for (MyGutterOperation operation : myOperations) { operation.update(force); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java index 7577e69532e7..52c21bac955b 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleDiffViewer.java @@ -236,13 +236,17 @@ public class SimpleDiffViewer extends TwosideTextDiffViewer { myPanel.addNotification(DiffNotifications.createEqualContents(equalCharsets, equalSeparators)); } - if (data.getFragments() != null) { - for (LineFragment fragment : data.getFragments()) { - myDiffChanges.add(new SimpleDiffChange(this, fragment)); + List fragments = data.getFragments(); + if (fragments != null) { + for (int i = 0; i < fragments.size(); i++) { + LineFragment fragment = fragments.get(i); + LineFragment previousFragment = i != 0 ? fragments.get(i - 1) : null; + + myDiffChanges.add(new SimpleDiffChange(this, fragment, previousFragment)); } } - myFoldingModel.install(data.getFragments(), myRequest, getFoldingModelSettings()); + myFoldingModel.install(fragments, myRequest, getFoldingModelSettings()); myInitialScrollHelper.onRediff(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleOnesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleOnesideDiffViewer.java index 30397b78726d..41c3585ecd75 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleOnesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleOnesideDiffViewer.java @@ -131,13 +131,6 @@ public class SimpleOnesideDiffViewer extends OnesideTextDiffViewer { TextDiffType type = getSide().select(TextDiffType.DELETED, TextDiffType.INSERTED); myHighlighters.addAll(DiffDrawUtil.createHighlighter(getEditor(), 0, getLineCount(document), type, false)); - - int startLine = 0; - int endLine = getLineCount(document); - - if (startLine != endLine) { - myHighlighters.addAll(DiffDrawUtil.createLineMarker(getEditor(), startLine, endLine, type, false)); - } } myInitialScrollHelper.onRediff(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/ThreesideDiffChangeBase.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/ThreesideDiffChangeBase.java index 5c67d5f255b3..ff588ccddcd5 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/ThreesideDiffChangeBase.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/ThreesideDiffChangeBase.java @@ -123,7 +123,6 @@ public abstract class ThreesideDiffChangeBase { boolean ignored = !resolved && getInnerFragments() != null; boolean shouldHideWithoutLineNumbers = side == ThreeSide.BASE && !isChange(Side.LEFT) && isChange(Side.RIGHT); myHighlighters.addAll(DiffDrawUtil.createHighlighter(editor, startLine, endLine, type, ignored, resolved, shouldHideWithoutLineNumbers)); - myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, startLine, endLine, type, resolved)); } protected void createInnerHighlighter(@NotNull ThreeSide side) { diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java index 4bef73b8f9dd..845976dd0d1e 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffDividerDrawUtil.java @@ -242,14 +242,28 @@ public class DiffDividerDrawUtil { } public void paint(Graphics2D g, int width, boolean paintBorder, boolean curve) { - // we need this shift, because editor background highlight is painted in range "Y(line) - 1 .. Y(line + 1) - 1" - int startY1 = myStart1 - 1; - int endY1 = myEnd1 - 1; - int startY2 = myStart2 - 1; - int endY2 = myEnd2 - 1; + int startY1; + int endY1; + int startY2; + int endY2; - if (endY1 - startY1 < 2) endY1 = startY1 + 1; - if (endY2 - startY2 < 2) endY2 = startY2 + 1; + if (myEnd1 - myStart1 < 2) { + startY1 = myStart1 - 1; + endY1 = myStart1; + } + else { + startY1 = myStart1; + endY1 = myEnd1 - 1; + } + + if (myEnd2 - myStart2 < 2) { + startY2 = myStart2 - 1; + endY2 = myStart2; + } + else { + startY2 = myStart2; + endY2 = myEnd2 - 1; + } Stroke oldStroke = g.getStroke(); if (myResolved) { diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java b/platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java index 61856165795c..78d33fc87a51 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java @@ -21,6 +21,8 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.ex.EditorGutterComponentEx; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.util.BooleanGetter; import com.intellij.openapi.util.TextRange; @@ -233,6 +235,34 @@ public class DiffDrawUtil { }; } + @NotNull + private static LineMarkerRenderer createFoldingGutterLineRenderer(@NotNull final TextDiffType type, + @NotNull final SeparatorPlacement placement, + final boolean doubleLine, + final boolean resolved) { + return new LineMarkerRendererEx() { + @Override + public void paint(Editor editor, Graphics g, Rectangle r) { + EditorGutterComponentEx gutter = ((EditorEx)editor).getGutterComponentEx(); + Graphics2D g2 = (Graphics2D)g; + + int x1 = gutter.getWhitespaceSeparatorOffset(); + int x2 = gutter.getWidth(); + + int y = r.y; + if (placement == SeparatorPlacement.BOTTOM) y += editor.getLineHeight(); + + drawChunkBorderLine(g2, x1, x2, y - 1, type.getColor(editor), doubleLine, resolved); + } + + @NotNull + @Override + public Position getPosition() { + return Position.CUSTOM; + } + }; + } + // // Highlighters // @@ -248,20 +278,14 @@ public class DiffDrawUtil { List list = new ArrayList<>(); if (!inserted.isEmpty() && !deleted.isEmpty()) { - list.addAll(createLineMarker(editor, deleted.start, TextDiffType.DELETED, SeparatorPlacement.TOP)); list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored)); list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored)); - list.addAll(createLineMarker(editor, inserted.end - 1, TextDiffType.INSERTED, SeparatorPlacement.BOTTOM)); } else if (!inserted.isEmpty()) { - list.addAll(createLineMarker(editor, inserted.start, TextDiffType.INSERTED, SeparatorPlacement.TOP)); list.addAll(createHighlighter(editor, inserted.start, inserted.end, TextDiffType.INSERTED, ignored)); - list.addAll(createLineMarker(editor, inserted.end - 1, TextDiffType.INSERTED, SeparatorPlacement.BOTTOM)); } else if (!deleted.isEmpty()) { - list.addAll(createLineMarker(editor, deleted.start, TextDiffType.DELETED, SeparatorPlacement.TOP)); list.addAll(createHighlighter(editor, deleted.start, deleted.end, TextDiffType.DELETED, ignored)); - list.addAll(createLineMarker(editor, deleted.end - 1, TextDiffType.DELETED, SeparatorPlacement.BOTTOM)); } if (innerFragments != null) { @@ -301,31 +325,20 @@ public class DiffDrawUtil { } @NotNull - public static List createLineMarker(@NotNull final Editor editor, int line1, int line2, - @NotNull final TextDiffType type, final boolean resolved) { - if (line1 == line2) { - if (line1 == 0) return Collections.emptyList(); - return createLineMarker(editor, line1 - 1, type, SeparatorPlacement.BOTTOM, true, resolved); - } - else { - return ContainerUtil.concat( - createLineMarker(editor, line1, type, SeparatorPlacement.TOP, false, resolved), - createLineMarker(editor, line2 - 1, type, SeparatorPlacement.BOTTOM, false, resolved) - ); - } - } - - @NotNull - public static List createLineMarker(@NotNull Editor editor, int line, @NotNull final TextDiffType type, - @NotNull final SeparatorPlacement placement) { - return new LineMarkerBuilder(editor, line, placement).withType(type).doneDefaultRenderer(); + public static List createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type) { + if (line == 0) return Collections.emptyList(); + return createLineMarker(editor, line - 1, type, SeparatorPlacement.BOTTOM, false, false, true); } @NotNull private static List createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type, @NotNull final SeparatorPlacement placement, - final boolean doubleLine, final boolean resolved) { - return new LineMarkerBuilder(editor, line, placement).withType(type).withResolved(resolved).doneDefaultRenderer(doubleLine); + boolean doubleLine, boolean resolved, boolean paintFoldingOutline) { + LineMarkerBuilder builder = new LineMarkerBuilder(editor, line, placement) + .withType(type).withResolved(resolved) + .withDefaultRenderer(doubleLine); + if (paintFoldingOutline) builder.withDefaultGutterRenderer(doubleLine); + return builder.done(); } @NotNull @@ -386,6 +399,8 @@ public class DiffDrawUtil { @NotNull public List done() { + List highlighters = new ArrayList<>(); + boolean isEmptyRange = startLine == endLine; boolean isLastLine = endLine == getLineCount(editor.getDocument()); @@ -398,16 +413,31 @@ public class DiffDrawUtil { RangeHighlighter highlighter = editor.getMarkupModel() .addRangeHighlighter(start, end, DEFAULT_LAYER, attributes, HighlighterTargetArea.LINES_IN_RANGE); + highlighters.add(highlighter); highlighter.setLineMarkerRenderer(new DiffLineMarkerRenderer(highlighter, type, ignored, resolved, hideWithoutLineNumbers, isEmptyRange, isLastLine)); - if (stripeAttributes == null) return Collections.singletonList(highlighter); + if (isEmptyRange) { + if (startLine == 0) { + highlighters.addAll(createLineMarker(editor, 0, type, SeparatorPlacement.TOP, true, resolved, false)); + } + else { + highlighters.addAll(createLineMarker(editor, startLine - 1, type, SeparatorPlacement.BOTTOM, true, resolved, false)); + } + } + else if (resolved) { + highlighters.addAll(createLineMarker(editor, startLine, type, SeparatorPlacement.TOP, false, resolved, false)); + highlighters.addAll(createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, false, resolved, false)); + } - RangeHighlighter stripeHighlighter = editor.getMarkupModel() - .addRangeHighlighter(start, end, STRIPE_LAYER, stripeAttributes, HighlighterTargetArea.LINES_IN_RANGE); + if (stripeAttributes != null) { + RangeHighlighter stripeHighlighter = editor.getMarkupModel() + .addRangeHighlighter(start, end, STRIPE_LAYER, stripeAttributes, HighlighterTargetArea.LINES_IN_RANGE); + highlighters.add(stripeHighlighter); + } - return ContainerUtil.list(highlighter, stripeHighlighter); + return highlighters; } } @@ -445,6 +475,7 @@ public class DiffDrawUtil { private boolean resolved = false; @Nullable private TextDiffType type; @Nullable private LineSeparatorRenderer renderer; + @Nullable private LineMarkerRenderer gutterRenderer; private LineMarkerBuilder(@NotNull Editor editor, int line, @NotNull SeparatorPlacement placement) { this.editor = editor; @@ -471,15 +502,17 @@ public class DiffDrawUtil { } @NotNull - public List doneDefaultRenderer() { - return doneDefaultRenderer(false); + public LineMarkerBuilder withDefaultRenderer(boolean doubleLine) { + assert type != null; + this.renderer = createDiffLineRenderer(editor, type, doubleLine, resolved); + return this; } @NotNull - public List doneDefaultRenderer(boolean doubleLine) { + public LineMarkerBuilder withDefaultGutterRenderer(boolean doubleLine) { assert type != null; - this.renderer = createDiffLineRenderer(editor, type, doubleLine, resolved); - return done(); + this.gutterRenderer = createFoldingGutterLineRenderer(type, placement, doubleLine, resolved); + return this; } @NotNull @@ -493,6 +526,7 @@ public class DiffDrawUtil { highlighter.setLineSeparatorPlacement(placement); highlighter.setLineSeparatorRenderer(renderer); + highlighter.setLineMarkerRenderer(gutterRenderer); if (type == null || resolved) return Collections.singletonList(highlighter); diff --git a/platform/diff-impl/src/com/intellij/diff/util/DiffLineMarkerRenderer.java b/platform/diff-impl/src/com/intellij/diff/util/DiffLineMarkerRenderer.java index f387071e3904..0f4022972f66 100644 --- a/platform/diff-impl/src/com/intellij/diff/util/DiffLineMarkerRenderer.java +++ b/platform/diff-impl/src/com/intellij/diff/util/DiffLineMarkerRenderer.java @@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull; import java.awt.*; -public class DiffLineMarkerRenderer implements LineMarkerRendererEx { +class DiffLineMarkerRenderer implements LineMarkerRendererEx { @NotNull private final RangeHighlighter myHighlighter; @NotNull private final TextDiffType myDiffType; private final boolean myIgnoredFoldingOutline; @@ -101,10 +101,10 @@ public class DiffLineMarkerRenderer implements LineMarkerRendererEx { if (!myResolved) { g2.setColor(ignoredBackgroundColor ? myDiffType.getIgnoredColor(editor) : color); g2.fillRect(x1, y1, x2 - x1, y2 - y1); + } else { + DiffDrawUtil.drawChunkBorderLine(g2, x1, x2, y1 - 1, color, false, myResolved); + DiffDrawUtil.drawChunkBorderLine(g2, x1, x2, y2 - 1, color, false, myResolved); } - - DiffDrawUtil.drawChunkBorderLine(g2, x1, x2, y1 - 1, color, false, myResolved); - DiffDrawUtil.drawChunkBorderLine(g2, x1, x2, y2 - 1, color, false, myResolved); } else { // range is empty - insertion or deletion diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchChange.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchChange.java index cc579dc2814c..6c89391cd346 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchChange.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/tool/ApplyPatchChange.java @@ -127,7 +127,6 @@ class ApplyPatchChange { boolean resolved = isRangeApplied(); myHighlighters.addAll(DiffDrawUtil.createHighlighter(editor, startLine, endLine, type, false, resolved, false)); - myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, startLine, endLine, type, resolved)); } private void createStatusHighlighter() {