diff: add annotate action to diff viewers
[idea/community.git] / platform / diff-impl / src / com / intellij / diff / tools / simple / SimpleThreesideDiffChange.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.diff.tools.simple;
17
18 import com.intellij.diff.comparison.ComparisonPolicy;
19 import com.intellij.diff.fragments.MergeLineFragment;
20 import com.intellij.diff.util.DiffDrawUtil;
21 import com.intellij.diff.util.DiffUtil;
22 import com.intellij.diff.util.TextDiffType;
23 import com.intellij.diff.util.ThreeSide;
24 import com.intellij.openapi.editor.Document;
25 import com.intellij.openapi.editor.Editor;
26 import com.intellij.openapi.editor.ex.EditorEx;
27 import com.intellij.openapi.editor.markup.RangeHighlighter;
28 import com.intellij.openapi.editor.markup.SeparatorPlacement;
29 import org.jetbrains.annotations.NotNull;
30
31 import java.util.ArrayList;
32 import java.util.List;
33
34 public class SimpleThreesideDiffChange extends ThreesideDiffChangeBase {
35   @NotNull private final List<? extends EditorEx> myEditors;
36   @NotNull private final MergeLineFragment myFragment;
37
38   @NotNull private final List<RangeHighlighter> myHighlighters = new ArrayList<RangeHighlighter>();
39
40   private int[] myLineStartShifts = new int[3];
41   private int[] myLineEndShifts = new int[3];
42
43   public SimpleThreesideDiffChange(@NotNull MergeLineFragment fragment,
44                                    @NotNull List<? extends EditorEx> editors,
45                                    @NotNull ComparisonPolicy policy) {
46     super(fragment, editors, policy);
47     myEditors = editors;
48     myFragment = fragment;
49
50     installHighlighter();
51   }
52
53   public void installHighlighter() {
54     assert myHighlighters.isEmpty();
55
56     createHighlighter(ThreeSide.BASE);
57     if (getType().isLeftChange()) createHighlighter(ThreeSide.LEFT);
58     if (getType().isRightChange()) createHighlighter(ThreeSide.RIGHT);
59   }
60
61   public void destroyHighlighter() {
62     for (RangeHighlighter highlighter : myHighlighters) {
63       highlighter.dispose();
64     }
65     myHighlighters.clear();
66   }
67
68   //
69   // Highlighting
70   //
71
72   private void createHighlighter(@NotNull ThreeSide side) {
73     Editor editor = side.select(myEditors);
74     Document document = editor.getDocument();
75
76     TextDiffType type = getDiffType();
77     int startLine = myFragment.getStartLine(side);
78     int endLine = myFragment.getEndLine(side);
79
80     int start;
81     int end;
82     if (startLine == endLine) {
83       start = end = startLine < DiffUtil.getLineCount(document) ? document.getLineStartOffset(startLine) : document.getTextLength();
84     }
85     else {
86       start = document.getLineStartOffset(startLine);
87       end = document.getLineEndOffset(endLine - 1);
88       if (end < document.getTextLength()) end++;
89     }
90
91     myHighlighters.addAll(DiffDrawUtil.createHighlighter(editor, start, end, type));
92
93     if (startLine == endLine) {
94       if (startLine != 0) myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM, true));
95     }
96     else {
97       myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, startLine, type, SeparatorPlacement.TOP));
98       myHighlighters.addAll(DiffDrawUtil.createLineMarker(editor, endLine - 1, type, SeparatorPlacement.BOTTOM));
99     }
100   }
101
102   //
103   // Getters
104   //
105
106   @Override
107   public int getStartLine(@NotNull ThreeSide side) {
108     return myFragment.getStartLine(side) + side.select(myLineStartShifts);
109   }
110
111   @Override
112   public int getEndLine(@NotNull ThreeSide side) {
113     return myFragment.getEndLine(side) + side.select(myLineEndShifts);
114   }
115
116   //
117   // Shift
118   //
119
120   public boolean processChange(int oldLine1, int oldLine2, int shift, @NotNull ThreeSide side) {
121     int line1 = getStartLine(side);
122     int line2 = getEndLine(side);
123     int sideIndex = side.getIndex();
124
125     DiffUtil.UpdatedLineRange newRange = DiffUtil.updateRangeOnModification(line1, line2, oldLine1, oldLine2, shift);
126     myLineStartShifts[sideIndex] += newRange.startLine - line1;
127     myLineEndShifts[sideIndex] += newRange.endLine - line2;
128
129     return newRange.damaged;
130   }
131 }