diff: do not show 'contents identical' if we can't calculate diff
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / diff / impl / highlighting / SimpleDiffPanelState.java
1 /*
2  * Copyright 2000-2009 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.openapi.diff.impl.highlighting;
17
18 import com.intellij.openapi.Disposable;
19 import com.intellij.openapi.application.ApplicationManager;
20 import com.intellij.openapi.diff.impl.ComparisonPolicy;
21 import com.intellij.openapi.diff.impl.ContentChangeListener;
22 import com.intellij.openapi.diff.impl.fragments.*;
23 import com.intellij.openapi.diff.impl.processing.DiffPolicy;
24 import com.intellij.openapi.diff.impl.processing.HighlightMode;
25 import com.intellij.openapi.diff.impl.processing.TextCompareProcessor;
26 import com.intellij.openapi.diff.impl.splitter.LineBlocks;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.util.Disposer;
29 import com.intellij.util.diff.FilesTooBigForDiffException;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32
33 import java.util.ArrayList;
34 import java.util.Iterator;
35 import java.util.List;
36
37 public abstract class SimpleDiffPanelState implements Disposable  {
38   protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT;
39   protected DiffPolicy myDiffPolicy;
40   protected HighlightMode myHighlightMode;
41   protected final EditorPlaceHolder myAppender1;
42   protected final EditorPlaceHolder myAppender2;
43   protected FragmentList myFragmentList = FragmentList.EMPTY;
44   protected final Project myProject;
45
46   public SimpleDiffPanelState(Project project, ContentChangeListener changeListener, @NotNull Disposable parentDisposable) {
47     myAppender1 = createEditorWrapper(project, changeListener, FragmentSide.SIDE1);
48     myAppender2 = createEditorWrapper(project, changeListener, FragmentSide.SIDE2);
49     myProject = project;
50     myDiffPolicy = DiffPolicy.LINES_WO_FORMATTING;
51     myHighlightMode = HighlightMode.BY_WORD;
52     Disposer.register(parentDisposable, this);
53   }
54
55   private EditorPlaceHolder createEditorWrapper(Project project, ContentChangeListener changeListener, FragmentSide side) {
56     EditorPlaceHolder editorWrapper = new EditorPlaceHolder(side, project, this);
57     editorWrapper.addListener(changeListener);
58     return editorWrapper;
59   }
60   
61   public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) {
62     myComparisonPolicy = comparisonPolicy;
63   }
64
65   public void setDiffPolicy(DiffPolicy diffPolicy) {
66     myDiffPolicy = diffPolicy;
67   }
68
69   public DiffPolicy getDiffPolicy() {
70     return myDiffPolicy;
71   }
72
73   public ComparisonPolicy getComparisonPolicy() {
74     return myComparisonPolicy;
75   }
76
77   public HighlightMode getHighlightMode() {
78     return myHighlightMode;
79   }
80
81   public void setHighlightMode(HighlightMode highlightMode) {
82     myHighlightMode = highlightMode;
83   }
84
85   public void dispose() {
86   }
87
88   private LineBlocks addMarkup(final List<LineFragment> lines) {
89     ApplicationManager.getApplication().runWriteAction(new Runnable() {
90       public void run() {
91         final FragmentHighlighterImpl fragmentHighlighter = new FragmentHighlighterImpl(myAppender1, myAppender2);
92         for (Iterator<LineFragment> iterator = lines.iterator(); iterator.hasNext();) {
93           LineFragment line = iterator.next();
94           fragmentHighlighter.setIsLast(!iterator.hasNext());
95           line.highlight(fragmentHighlighter);
96         }
97       }
98     });
99     ArrayList<LineFragment> allLineFragments = new ArrayList<LineFragment>();
100     for (LineFragment lineFragment : lines) {
101       allLineFragments.add(lineFragment);
102       lineFragment.addAllDescendantsTo(allLineFragments);
103     }
104     myFragmentList = FragmentListImpl.fromList(allLineFragments);
105     return LineBlocks.fromLineFragments(allLineFragments);
106   }
107
108   private void resetMarkup() {
109     ApplicationManager.getApplication().runWriteAction(new ResetMarkupRunnable(this));
110   }
111
112   @Nullable
113   public LineBlocks updateEditors() throws FilesTooBigForDiffException {
114     resetMarkup();
115     if (myAppender1.getEditor() == null || myAppender2.getEditor() == null) {
116       return null;
117     }
118
119     return addMarkup(
120       new TextCompareProcessor(myComparisonPolicy, myDiffPolicy, myHighlightMode).process(myAppender1.getText(), myAppender2.getText()));
121   }
122
123   public Project getProject() { return myProject; }
124
125   public FragmentList getFragmentList() { return myFragmentList; }
126
127   private static class ResetMarkupRunnable implements Runnable {
128     private final SimpleDiffPanelState myState;
129
130     public ResetMarkupRunnable(SimpleDiffPanelState state) {
131       myState = state;
132     }
133
134     public void run() {
135       myState.myAppender1.resetHighlighters();
136       myState.myAppender2.resetHighlighters();
137     }
138   }
139 }