a701098d79426c9018707dd8930cf139ee29240b
[idea/community.git] / plugins / hg4idea / src / org / zmlx / hg4idea / provider / annotate / HgAnnotation.java
1 /*
2  * Copyright 2008-2010 Victor Iacoban
3  * Copyright 2000-2012 JetBrains s.r.o.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16 */
17 package org.zmlx.hg4idea.provider.annotate;
18
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.vcs.VcsKey;
21 import com.intellij.openapi.vcs.annotate.FileAnnotation;
22 import com.intellij.openapi.vcs.annotate.LineAnnotationAspect;
23 import com.intellij.openapi.vcs.annotate.LineAnnotationAspectAdapter;
24 import com.intellij.openapi.vcs.annotate.ShowAllAffectedGenericAction;
25 import com.intellij.openapi.vcs.history.VcsFileRevision;
26 import com.intellij.openapi.vcs.history.VcsRevisionNumber;
27 import com.intellij.openapi.vfs.LocalFileSystem;
28 import com.intellij.openapi.vfs.VirtualFile;
29 import com.intellij.util.containers.ContainerUtil;
30 import git4idea.annotate.AnnotationTooltipBuilder;
31 import org.jetbrains.annotations.Nls;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34 import org.zmlx.hg4idea.HgBundle;
35 import org.zmlx.hg4idea.HgFile;
36 import org.zmlx.hg4idea.HgFileRevision;
37 import org.zmlx.hg4idea.HgVcs;
38
39 import java.util.Date;
40 import java.util.LinkedList;
41 import java.util.List;
42
43 public class HgAnnotation extends FileAnnotation {
44
45   private StringBuilder myContentBuffer;
46
47   public enum FIELD {
48     USER, REVISION, DATE, LINE, CONTENT
49   }
50
51   private final HgLineAnnotationAspect dateAnnotationAspect = new HgLineAnnotationAspect(FIELD.DATE);
52   private final HgLineAnnotationAspect userAnnotationAspect = new HgLineAnnotationAspect(FIELD.USER);
53   private final HgLineAnnotationAspect revisionAnnotationAspect = new HgLineAnnotationAspect(FIELD.REVISION);
54
55   @NotNull private final Project myProject;
56   @NotNull private final List<? extends HgAnnotationLine> myLines;
57   @NotNull private final List<? extends HgFileRevision> myFileRevisions;
58   @NotNull private final HgFile myFile;
59   private final VcsRevisionNumber myCurrentRevision;
60
61   public HgAnnotation(@NotNull Project project, @NotNull HgFile hgFile, @NotNull List<? extends HgAnnotationLine> lines,
62                       @NotNull List<? extends HgFileRevision> vcsFileRevisions, VcsRevisionNumber revision) {
63     super(project);
64     myProject = project;
65     myLines = lines;
66     myFileRevisions = vcsFileRevisions;
67     myFile = hgFile;
68     myCurrentRevision = revision;
69   }
70
71   @Override
72   public int getLineCount() {
73     return myLines.size();
74   }
75
76   @Override
77   public void dispose() {
78   }
79
80   @Override
81   public LineAnnotationAspect[] getAspects() {
82     return new LineAnnotationAspect[] {
83       revisionAnnotationAspect,
84       dateAnnotationAspect,
85       userAnnotationAspect
86     };
87   }
88
89   @Nullable
90   @Override
91   public String getToolTip(int lineNumber) {
92     return getToolTip(lineNumber, false);
93   }
94
95   @Nullable
96   @Override
97   public String getHtmlToolTip(int lineNumber) {
98     return getToolTip(lineNumber, true);
99   }
100
101   @Nls
102   @Nullable
103   private String getToolTip(int lineNumber, boolean asHtml) {
104     if ( myLines.size() <= lineNumber || lineNumber < 0 ) {
105       return null;
106     }
107     HgAnnotationLine info = myLines.get(lineNumber);
108     if (info == null) {
109       return null;
110     }
111
112     HgFileRevision revision = ContainerUtil.find(myFileRevisions, it -> it.getRevisionNumber().equals(info.getVcsRevisionNumber()));
113     if (revision == null) return null;
114
115     AnnotationTooltipBuilder atb = new AnnotationTooltipBuilder(myProject, asHtml);
116     atb.appendRevisionLine(revision.getRevisionNumber(), null);
117     atb.appendLine(HgBundle.message("hg4idea.annotation.author", revision.getAuthor()));
118     atb.appendLine(HgBundle.message("hg4idea.annotation.date", revision.getRevisionDate()));
119     String message = revision.getCommitMessage();
120     if (message != null) atb.appendCommitMessageBlock(message);
121     return atb.toString(); //NON-NLS
122   }
123
124   @Override
125   public String getAnnotatedContent() {
126     if (myContentBuffer == null) {
127       myContentBuffer = new StringBuilder();
128       for (HgAnnotationLine line : myLines) {
129         myContentBuffer.append(line.get(FIELD.CONTENT));
130       }
131     }
132     return myContentBuffer.toString();
133   }
134
135   @Override
136   @Nullable
137   public VcsRevisionNumber getLineRevisionNumber(int lineNumber) {
138     if (lineNumber >= myLines.size() || lineNumber < 0) {
139       return null;
140     }
141     HgAnnotationLine annotationLine = myLines.get(lineNumber);
142     return annotationLine.getVcsRevisionNumber();
143   }
144
145   @Override
146   @Nullable
147   public Date getLineDate(int lineNumber) {
148     if (lineNumber >= myLines.size() || lineNumber < 0) {
149       return null;
150     }
151     //lines.get(lineNumber).get(HgAnnotation.FIELD.DATE)
152     // todo : parse date
153     return null;
154   }
155
156   @Override
157   @Nullable
158   public List<VcsFileRevision> getRevisions() {
159     List<VcsFileRevision> result = new LinkedList<>();
160     result.addAll(myFileRevisions);
161     return result;
162   }
163
164   @Nullable
165   private static String id(FIELD field) {
166     switch (field) {
167       case USER: return LineAnnotationAspect.AUTHOR;
168       case REVISION: return LineAnnotationAspect.REVISION;
169       case DATE: return LineAnnotationAspect.DATE;
170       default: return null;
171     }
172   }
173
174   private static boolean isShowByDefault(FIELD aspectType) {
175     return aspectType == FIELD.DATE || aspectType == FIELD.USER;
176   }
177
178   private class HgLineAnnotationAspect extends LineAnnotationAspectAdapter {
179     private final FIELD myAspectType;
180
181     HgLineAnnotationAspect(FIELD aspectType) {
182       super(id(aspectType), HgAnnotation.isShowByDefault(aspectType));
183       this.myAspectType = aspectType;
184     }
185
186     @Override
187     public String getValue(int lineNumber) {
188       if (lineNumber >= myLines.size() || lineNumber < 0) {
189         return "";
190       }
191       HgAnnotationLine annotationLine = myLines.get(lineNumber);
192       return myAspectType == FIELD.REVISION
193         ? annotationLine.getVcsRevisionNumber().asString()
194         : annotationLine.get(myAspectType).toString();
195     }
196
197     @Override
198     protected void showAffectedPaths(int lineNum) {
199       if (lineNum >= 0 && lineNum < myLines.size()) {
200         HgAnnotationLine line = myLines.get(lineNum);
201         VirtualFile file = myFile.toFilePath().getVirtualFile();
202         if (line != null && file != null) {
203           ShowAllAffectedGenericAction.showSubmittedFiles(myProject, line.getVcsRevisionNumber(), file, HgVcs.getKey());
204         }
205       }
206     }
207   }
208
209   @Nullable
210   @Override
211   public VcsRevisionNumber getCurrentRevision() {
212     return myCurrentRevision;
213   }
214
215   @Override
216   public VcsKey getVcsKey() {
217     return HgVcs.getKey();
218   }
219
220   @Override
221   public VirtualFile getFile() {
222     return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myFile.getFile());
223   }
224 }