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