Merge branch 'master' into new-merge
authorAleksey Pivovarov <AMPivovarov@gmail.com>
Wed, 29 Jul 2015 13:59:38 +0000 (16:59 +0300)
committerAleksey Pivovarov <AMPivovarov@gmail.com>
Wed, 29 Jul 2015 13:59:38 +0000 (16:59 +0300)
# Conflicts:
# platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java
# platform/diff-impl/src/com/intellij/diff/merge/TextMergeChange.java

1  2 
platform/diff-impl/src/com/intellij/diff/merge/TextMergeChange.java
platform/diff-impl/src/com/intellij/diff/tools/fragmented/UnifiedDiffChange.java
platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffChange.java
platform/diff-impl/src/com/intellij/diff/util/DiffDrawUtil.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java
platform/platform-resources-en/src/messages/ActionsBundle.properties
platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
platform/platform-resources/src/META-INF/PlatformExtensions.xml

index 9088a037ec8b506e9c02f0d053468894dcba8d01,0000000000000000000000000000000000000000..96582a9b5e08a68745c9cf8a3331976cdca1b953
mode 100644,000000..100644
--- /dev/null
@@@ -1,385 -1,0 +1,385 @@@
-     myHighlighters.add(DiffDrawUtil.createHighlighter(editor, start, end, type, false, HighlighterTargetArea.EXACT_RANGE, resolved));
 +/*
 + * Copyright 2000-2015 JetBrains s.r.o.
 + *
 + * Licensed under the Apache License, Version 2.0 (the "License");
 + * you may not use this file except in compliance with the License.
 + * You may obtain a copy of the License at
 + *
 + * http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the License is distributed on an "AS IS" BASIS,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the License for the specific language governing permissions and
 + * limitations under the License.
 + */
 +package com.intellij.diff.merge;
 +
 +import com.intellij.diff.comparison.ComparisonPolicy;
 +import com.intellij.diff.fragments.MergeLineFragment;
 +import com.intellij.diff.tools.simple.ThreesideDiffChangeBase;
 +import com.intellij.diff.util.*;
 +import com.intellij.diff.util.DiffUtil.UpdatedLineRange;
 +import com.intellij.icons.AllIcons;
 +import com.intellij.openapi.actionSystem.AnAction;
 +import com.intellij.openapi.actionSystem.AnActionEvent;
 +import com.intellij.openapi.diff.DiffBundle;
 +import com.intellij.openapi.editor.Document;
 +import com.intellij.openapi.editor.Editor;
 +import com.intellij.openapi.editor.ex.EditorEx;
 +import com.intellij.openapi.editor.markup.*;
 +import com.intellij.openapi.project.DumbAwareAction;
 +import com.intellij.util.containers.ContainerUtil;
 +import org.jetbrains.annotations.CalledInAwt;
 +import org.jetbrains.annotations.NotNull;
 +import org.jetbrains.annotations.Nullable;
 +
 +import javax.swing.*;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +public class TextMergeChange extends ThreesideDiffChangeBase {
 +  @NotNull private final TextMergeTool.TextMergeViewer myMergeViewer;
 +  @NotNull private final TextMergeTool.TextMergeViewer.MyThreesideViewer myViewer;
 +  @NotNull private final List<RangeHighlighter> myHighlighters = new ArrayList<RangeHighlighter>();
 +
 +  @NotNull private final List<MyGutterOperation> myOperations = new ArrayList<MyGutterOperation>();
 +
 +  private int[] myStartLines = new int[3];
 +  private int[] myEndLines = new int[3];
 +  private final boolean[] myResolved = new boolean[2];
 +
 +  @CalledInAwt
 +  public TextMergeChange(@NotNull MergeLineFragment fragment, @NotNull TextMergeTool.TextMergeViewer viewer) {
 +    super(fragment, viewer.getViewer().getEditors(), ComparisonPolicy.DEFAULT);
 +    myMergeViewer = viewer;
 +    myViewer = viewer.getViewer();
 +
 +    for (ThreeSide side : ThreeSide.values()) {
 +      myStartLines[side.getIndex()] = fragment.getStartLine(side);
 +      myEndLines[side.getIndex()] = fragment.getEndLine(side);
 +    }
 +
 +    installHighlighter();
 +  }
 +
 +  protected void installHighlighter() {
 +    assert myHighlighters.isEmpty();
 +
 +    createHighlighter(ThreeSide.BASE);
 +    if (getType().isLeftChange()) createHighlighter(ThreeSide.LEFT);
 +    if (getType().isRightChange()) createHighlighter(ThreeSide.RIGHT);
 +
 +    doInstallActionHighlighters();
 +  }
 +
 +  @CalledInAwt
 +  public void destroyHighlighter() {
 +    for (RangeHighlighter highlighter : myHighlighters) {
 +      highlighter.dispose();
 +    }
 +    myHighlighters.clear();
 +
 +    for (MyGutterOperation operation : myOperations) {
 +      operation.dispose();
 +    }
 +    myOperations.clear();
 +  }
 +
 +  @CalledInAwt
 +  public void doReinstallHighlighter() {
 +    destroyHighlighter();
 +    installHighlighter();
 +    myViewer.repaintDividers();
 +  }
 +
 +  private void createHighlighter(@NotNull ThreeSide side) {
 +    Editor editor = side.select(myViewer.getEditors());
 +    Document document = editor.getDocument();
 +
 +    TextDiffType type = getDiffType();
 +    boolean resolved = isResolved(side);
 +    int startLine = getStartLine(side);
 +    int endLine = getEndLine(side);
 +
 +    int start;
 +    int end;
 +    if (startLine == endLine) {
 +      start = end = startLine < DiffUtil.getLineCount(document) ? document.getLineStartOffset(startLine) : document.getTextLength();
 +    }
 +    else {
 +      start = document.getLineStartOffset(startLine);
 +      end = document.getLineEndOffset(endLine - 1);
 +      if (end < document.getTextLength()) end++;
 +    }
 +
-         myHighlighters.add(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, true, resolved));
++    myHighlighters.addAll(DiffDrawUtil.createHighlighter(editor, start, end, type, false, HighlighterTargetArea.EXACT_RANGE, resolved));
 +
 +    if (startLine == endLine) {
 +      if (startLine != 0) {
-       myHighlighters.add(DiffDrawUtil.createLineMarker(editor, startLine, type, SeparatorPlacement.TOP, false, resolved));
-       myHighlighters.add(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, false, resolved));
++        myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, true, resolved));
 +      }
 +    }
 +    else {
++      myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, startLine, type, SeparatorPlacement.TOP, false, resolved));
++      myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, false, resolved));
 +    }
 +  }
 +
 +  //
 +  // Getters
 +  //
 +
 +  @CalledInAwt
 +  public void markResolved() {
 +    if (isResolved()) return;
 +    myResolved[0] = true;
 +    myResolved[1] = true;
 +    myViewer.onChangeResolved(this);
 +    myViewer.reinstallHighlighter(this);
 +  }
 +
 +  @CalledInAwt
 +  public void markResolved(@NotNull Side side) {
 +    if (isResolved(side)) return;
 +    myResolved[side.getIndex()] = true;
 +    if (isResolved()) myViewer.onChangeResolved(this);
 +    myViewer.reinstallHighlighter(this);
 +  }
 +
 +  public boolean isResolved() {
 +    return myResolved[0] && myResolved[1];
 +  }
 +
 +  public boolean isResolved(@NotNull Side side) {
 +    return side.select(myResolved);
 +  }
 +
 +  public boolean isResolved(@NotNull ThreeSide side) {
 +    switch (side) {
 +      case LEFT:
 +        return isResolved(Side.LEFT);
 +      case BASE:
 +        return isResolved();
 +      case RIGHT:
 +        return isResolved(Side.RIGHT);
 +      default:
 +        throw new IllegalArgumentException(side.toString());
 +    }
 +  }
 +
 +  public int getStartLine(@NotNull ThreeSide side) {
 +    return side.select(myStartLines);
 +  }
 +
 +  public int getEndLine(@NotNull ThreeSide side) {
 +    return side.select(myEndLines);
 +  }
 +
 +  public void setStartLine(@NotNull ThreeSide side, int value) {
 +    myStartLines[side.getIndex()] = value;
 +  }
 +
 +  public void setEndLine(@NotNull ThreeSide side, int value) {
 +    myEndLines[side.getIndex()] = value;
 +  }
 +
 +  //
 +  // Shift
 +  //
 +
 +  public boolean processBaseChange(int oldLine1, int oldLine2, int shift) {
 +    int line1 = getStartLine(ThreeSide.BASE);
 +    int line2 = getEndLine(ThreeSide.BASE);
 +    int baseIndex = ThreeSide.BASE.getIndex();
 +
 +    UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(line1, line2, oldLine1, oldLine2, shift);
 +    myStartLines[baseIndex] = newRange.startLine;
 +    myEndLines[baseIndex] = newRange.endLine;
 +
 +    boolean rangeAffected = oldLine2 >= line1 && oldLine1 <= line2; // RangeMarker can be updated in a different way
 +
 +    if (newRange.startLine == newRange.endLine && getDiffType() == TextDiffType.DELETED) {
 +      markResolved();
 +    }
 +
 +    return newRange.damaged || rangeAffected;
 +  }
 +
 +  //
 +  // Gutter actions
 +  //
 +
 +  private void doInstallActionHighlighters() {
 +    ContainerUtil.addIfNotNull(myOperations, createOperation(ThreeSide.LEFT));
 +    ContainerUtil.addIfNotNull(myOperations, createOperation(ThreeSide.BASE));
 +    ContainerUtil.addIfNotNull(myOperations, createOperation(ThreeSide.RIGHT));
 +  }
 +
 +  @Nullable
 +  private MyGutterOperation createOperation(@NotNull ThreeSide side) {
 +    if (isResolved(side)) return null;
 +
 +    EditorEx editor = myViewer.getEditor(side);
 +    Document document = editor.getDocument();
 +
 +    int line = getStartLine(side);
 +    int offset = line == DiffUtil.getLineCount(document) ? document.getTextLength() : document.getLineStartOffset(line);
 +
 +    RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(offset, offset,
 +                                                                               HighlighterLayer.ADDITIONAL_SYNTAX,
 +                                                                               null,
 +                                                                               HighlighterTargetArea.LINES_IN_RANGE);
 +    return new MyGutterOperation(side, highlighter);
 +  }
 +
 +  public void updateGutterActions(boolean force) {
 +    for (MyGutterOperation operation : myOperations) {
 +      operation.update(force);
 +    }
 +  }
 +
 +  private class MyGutterOperation {
 +    @NotNull private final ThreeSide mySide;
 +    @NotNull private final RangeHighlighter myHighlighter;
 +
 +    private boolean myCtrlPressed;
 +    private boolean myShiftPressed;
 +
 +    private MyGutterOperation(@NotNull ThreeSide side, @NotNull RangeHighlighter highlighter) {
 +      mySide = side;
 +      myHighlighter = highlighter;
 +
 +      update(true);
 +    }
 +
 +    public void dispose() {
 +      myHighlighter.dispose();
 +    }
 +
 +    public void update(boolean force) {
 +      if (!force && !areModifiersChanged()) {
 +        return;
 +      }
 +      if (myHighlighter.isValid()) myHighlighter.setGutterIconRenderer(createRenderer());
 +    }
 +
 +    private boolean areModifiersChanged() {
 +      return myCtrlPressed != myViewer.getModifierProvider().isCtrlPressed() ||
 +             myShiftPressed != myViewer.getModifierProvider().isShiftPressed();
 +    }
 +
 +    @Nullable
 +    public GutterIconRenderer createRenderer() {
 +      myCtrlPressed = myViewer.getModifierProvider().isCtrlPressed();
 +      myShiftPressed = myViewer.getModifierProvider().isShiftPressed();
 +
 +      if (mySide == ThreeSide.BASE) {
 +        return createRevertRenderer();
 +      }
 +      else {
 +        Side versionSide = mySide.select(Side.LEFT, null, Side.RIGHT);
 +        assert versionSide != null;
 +
 +        if (!isChange(versionSide)) return null;
 +
 +        boolean isAppendable = getStartLine(mySide) != getEndLine(mySide) &&
 +                               (getStartLine(ThreeSide.BASE) != getEndLine(ThreeSide.BASE) || isConflict());
 +
 +        if (myShiftPressed) {
 +          return createRevertRenderer();
 +        }
 +        if (myCtrlPressed && isAppendable) {
 +          return createAppendRenderer(versionSide);
 +        }
 +        return createApplyRenderer(versionSide);
 +      }
 +    }
 +  }
 +
 +  @Nullable
 +  private GutterIconRenderer createApplyRenderer(@NotNull final Side side) {
 +    return createIconRenderer(DiffBundle.message("merge.dialog.apply.change.action.name"), AllIcons.Diff.Arrow, new Runnable() {
 +      @Override
 +      public void run() {
 +        final Document document = myViewer.getEditor(ThreeSide.BASE).getDocument();
 +        DiffUtil.executeWriteCommand(document, myViewer.getProject(), "Apply change", new Runnable() {
 +          @Override
 +          public void run() {
 +            myViewer.replaceChange(TextMergeChange.this, side);
 +          }
 +        });
 +      }
 +    });
 +  }
 +
 +  @Nullable
 +  private GutterIconRenderer createAppendRenderer(@NotNull final Side side) {
 +    return createIconRenderer(DiffBundle.message("merge.dialog.append.change.action.name"), AllIcons.Diff.ArrowLeftDown, new Runnable() {
 +      @Override
 +      public void run() {
 +        final Document document = myViewer.getEditor(ThreeSide.BASE).getDocument();
 +        DiffUtil.executeWriteCommand(document, myViewer.getProject(), "Apply change", new Runnable() {
 +          @Override
 +          public void run() {
 +            myViewer.appendChange(TextMergeChange.this, side);
 +          }
 +        });
 +      }
 +    });
 +  }
 +
 +  @Nullable
 +  private GutterIconRenderer createRevertRenderer() {
 +    return createIconRenderer(DiffBundle.message("merge.dialog.ignore.change.action.name"), AllIcons.Diff.Remove, new Runnable() {
 +      @Override
 +      public void run() {
 +        markResolved();
 +      }
 +    });
 +  }
 +
 +  @Nullable
 +  private GutterIconRenderer createIconRenderer(@NotNull final String tooltipText,
 +                                                @NotNull final Icon icon,
 +                                                @NotNull final Runnable perform) {
 +    return new GutterIconRenderer() {
 +      @NotNull
 +      @Override
 +      public Icon getIcon() {
 +        return icon;
 +      }
 +
 +      public boolean isNavigateAction() {
 +        return true;
 +      }
 +
 +      @Nullable
 +      @Override
 +      public AnAction getClickAction() {
 +        return new DumbAwareAction() {
 +          @Override
 +          public void actionPerformed(AnActionEvent e) {
 +            perform.run();
 +          }
 +        };
 +      }
 +
 +      @Override
 +      public boolean equals(Object obj) {
 +        return obj == this;
 +      }
 +
 +      @Override
 +      public int hashCode() {
 +        return System.identityHashCode(this);
 +      }
 +
 +      @Nullable
 +      @Override
 +      public String getTooltipText() {
 +        return tooltipText;
 +      }
 +    };
 +  }
 +}
index bd6adae774690545f20448434576326918fe9218,ac4f0f9403914bded852a87dad5b1c76c62b0835..6d17aef6c1f080c39d73236d04ec3fec77890e98
@@@ -78,28 -86,6 +86,31 @@@ public class DiffDrawUtil 
      UIUtil.drawLine(g, x1, y, x2, y, null, color);
    }
  
-     } else if (dottedLine) {
 +  public static void drawDottedDoubleChunkBorderLine(@NotNull Graphics2D g, int x1, int x2, int y, @NotNull Color color) {
 +    UIUtil.drawBoldDottedLine(g, x1, x2, y - 1, null, color, false);
 +    UIUtil.drawBoldDottedLine(g, x1, x2, y, null, color, false);
 +  }
 +
 +  public static void drawDottedChunkBorderLine(@NotNull Graphics2D g, int x1, int x2, int y, @NotNull Color color) {
 +    UIUtil.drawBoldDottedLine(g, x1, x2, y - 1, null, color, false);
 +  }
 +
 +  public static void drawChunkBorderLine(@NotNull Graphics2D g, int x1, int x2, int y, @NotNull Color color,
 +                                         boolean doubleLine, boolean dottedLine) {
 +    if (dottedLine && doubleLine) {
 +      drawDottedDoubleChunkBorderLine(g, x1, x2, y, color);
-     } else if (doubleLine) {
++    }
++    else if (dottedLine) {
 +      drawDottedChunkBorderLine(g, x1, x2, y, color);
-     } else {
++    }
++    else if (doubleLine) {
 +      drawDoubleChunkBorderLine(g, x1, x2, y, color);
++    }
++    else {
 +      drawChunkBorderLine(g, x1, x2, y, color);
 +    }
 +  }
 +
    public static void drawTrapezium(@NotNull Graphics2D g,
                                     int x1, int x2,
                                     int start1, int end1,
      };
    }
  
 -                                            boolean ignoredFoldingOutline) {
 -    highlighter.setLineMarkerRenderer(new DiffLineMarkerRenderer(type, ignoredFoldingOutline));
+   private static void installGutterRenderer(@NotNull RangeHighlighter highlighter,
+                                             @NotNull TextDiffType type,
++                                            boolean ignoredFoldingOutline,
++                                            boolean resolved) {
++    highlighter.setLineMarkerRenderer(new DiffLineMarkerRenderer(type, ignoredFoldingOutline, resolved));
+   }
+   private static void installEmptyRangeRenderer(@NotNull RangeHighlighter highlighter,
+                                                 @NotNull TextDiffType type) {
+     highlighter.setCustomRenderer(new DiffEmptyHighlighterRenderer(type));
+   }
    //
    // Highlighters
    //
      return createHighlighter(editor, start, end, type, ignored, HighlighterTargetArea.EXACT_RANGE);
    }
  
 -
    @NotNull
-   public static RangeHighlighter createHighlighter(@NotNull Editor editor, int start, int end, @NotNull TextDiffType type,
-                                                    boolean ignored, @NotNull HighlighterTargetArea area) {
+   public static List<RangeHighlighter> createHighlighter(@NotNull Editor editor, int start, int end, @NotNull TextDiffType type,
+                                                          boolean ignored, @NotNull HighlighterTargetArea area) {
 -    TextAttributes attributes = start != end ? getTextAttributes(type, editor, ignored) : null;
 -    TextAttributes stripeAttributes = start != end ? getStripeTextAttributes(type, editor) : null;
 +    return createHighlighter(editor, start, end, type, ignored, area, false);
 +  }
 +
 +  @NotNull
-   public static RangeHighlighter createHighlighter(@NotNull Editor editor, int start, int end, @NotNull TextDiffType type,
-                                                    boolean ignored, @NotNull HighlighterTargetArea area, boolean resolved) {
-     TextAttributes attributes = resolved ? null : getTextAttributes(type, editor, ignored, true);
++  public static List<RangeHighlighter> createHighlighter(@NotNull Editor editor, int start, int end, @NotNull TextDiffType type,
++                                                         boolean ignored, @NotNull HighlighterTargetArea area, boolean resolved) {
++    TextAttributes attributes = start != end && !resolved ? getTextAttributes(type, editor, ignored) : null;
++    TextAttributes stripeAttributes = start != end && !resolved ? getStripeTextAttributes(type, editor) : null;
  
-     RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(start, end, HighlighterLayer.SELECTION - 3,
-                                                                                start != end ? attributes : null, area);
-     // TODO: diff looks cool with wide markers. Maybe we can keep them ?
-     highlighter.setThinErrorStripeMark(true);
+     RangeHighlighter highlighter = editor.getMarkupModel()
+       .addRangeHighlighter(start, end, DEFAULT_LAYER, attributes, area);
  
 -    installGutterRenderer(highlighter, type, ignored);
 +    installGutterRenderer(highlighter, type, ignored, resolved);
  
-     return highlighter;
+     if (stripeAttributes == null) return Collections.singletonList(highlighter);
+     RangeHighlighter stripeHighlighter = editor.getMarkupModel()
+       .addRangeHighlighter(start, end, STRIPE_LAYER, stripeAttributes, area);
+     return ContainerUtil.list(highlighter, stripeHighlighter);
    }
  
    @NotNull
    }
  
    @NotNull
-   public static RangeHighlighter createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type,
-                                                   @NotNull final SeparatorPlacement placement, final boolean doubleLine) {
+   public static List<RangeHighlighter> createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type,
+                                                         @NotNull final SeparatorPlacement placement, final boolean doubleLine) {
 +    return createLineMarker(editor, line, type, placement, doubleLine, false);
 +  }
 +
 +  @NotNull
-   public static RangeHighlighter createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type,
-                                                   @NotNull final SeparatorPlacement placement, final boolean doubleLine,
-                                                   final boolean applied) {
-     TextAttributes attributes = applied ? null : getStripeTextAttributes(type, editor);
++  public static List<RangeHighlighter> createLineMarker(@NotNull final Editor editor, int line, @NotNull final TextDiffType type,
++                                                        @NotNull final SeparatorPlacement placement, final boolean doubleLine,
++                                                        final boolean applied) {
      LineSeparatorRenderer renderer = new LineSeparatorRenderer() {
        @Override
        public void drawLine(Graphics g, int x1, int x2, int y) {
          // TODO: change LineSeparatorRenderer interface ?
          Rectangle clip = g.getClipBounds();
          x2 = clip.x + clip.width;
 -        if (doubleLine) {
 -          drawDoubleChunkBorderLine((Graphics2D)g, x1, x2, y, type.getColor(editor));
 -        }
 -        else {
 -          drawChunkBorderLine((Graphics2D)g, x1, x2, y, type.getColor(editor));
 -        }
 +        drawChunkBorderLine((Graphics2D)g, x1, x2, y, type.getColor(editor), doubleLine, applied);
        }
      };
-     return createLineMarker(editor, line, placement, attributes, renderer);
 -    return createLineMarker(editor, line, placement, type, renderer);
++    return createLineMarker(editor, line, placement, type, renderer, applied);
    }
  
    @NotNull
          g.drawLine(x1, y, x2, y);
        }
      };
--    return createLineMarker(editor, line, placement, null, renderer);
++    return createLineMarker(editor, line, placement, null, renderer, false);
    }
  
    @NotNull
-   public static RangeHighlighter createLineMarker(@NotNull final Editor editor, int line, @NotNull final SeparatorPlacement placement,
-                                                   @Nullable TextAttributes attributes, @NotNull LineSeparatorRenderer renderer) {
+   public static List<RangeHighlighter> createLineMarker(@NotNull final Editor editor, int line, @NotNull final SeparatorPlacement placement,
 -                                                        @Nullable TextDiffType type, @NotNull LineSeparatorRenderer renderer) {
++                                                        @Nullable TextDiffType type, @NotNull LineSeparatorRenderer renderer, boolean applied) {
+     // We won't use addLineHighlighter as it will fail to add marker into empty document.
+     //RangeHighlighter highlighter = editor.getMarkupModel().addLineHighlighter(line, HighlighterLayer.SELECTION - 1, null);
      int offset = DocumentUtil.getFirstNonSpaceCharOffset(editor.getDocument(), line);
-     RangeHighlighter marker = editor.getMarkupModel().addRangeHighlighter(offset, offset, HighlighterLayer.SELECTION - 1, attributes,
-                                                                           HighlighterTargetArea.LINES_IN_RANGE);
-     marker.setThinErrorStripeMark(true);
+     RangeHighlighter highlighter = editor.getMarkupModel()
+       .addRangeHighlighter(offset, offset, LINE_MARKER_LAYER, null, HighlighterTargetArea.LINES_IN_RANGE);
  
-     // We won't use addLineHighlighter as it will fail to add marker into empty document.
-     //RangeHighlighter marker = editor.getMarkupModel().addLineHighlighter(line, HighlighterLayer.SELECTION - 1, null);
+     highlighter.setLineSeparatorPlacement(placement);
+     highlighter.setLineSeparatorRenderer(renderer);
  
-     marker.setLineSeparatorPlacement(placement);
-     marker.setLineSeparatorRenderer(renderer);
 -    if (type == null) return Collections.singletonList(highlighter);
++    if (type == null || applied) return Collections.singletonList(highlighter);
+     TextAttributes stripeAttributes = getStripeTextAttributes(type, editor);
+     RangeHighlighter stripeHighlighter = editor.getMarkupModel()
+       .addRangeHighlighter(offset, offset, STRIPE_LAYER, stripeAttributes, HighlighterTargetArea.LINES_IN_RANGE);
  
-     return marker;
+     return ContainerUtil.list(highlighter, stripeHighlighter);
    }
  
    @NotNull