diff: add annotate action to diff viewers
[idea/community.git] / platform / diff-impl / src / com / intellij / diff / actions / CompareFilesAction.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.actions;
17
18 import com.intellij.diff.DiffRequestFactory;
19 import com.intellij.diff.requests.DiffRequest;
20 import com.intellij.ide.highlighter.ArchiveFileType;
21 import com.intellij.ide.util.PropertiesComponent;
22 import com.intellij.openapi.actionSystem.AnActionEvent;
23 import com.intellij.openapi.actionSystem.CommonDataKeys;
24 import com.intellij.openapi.actionSystem.DataKey;
25 import com.intellij.openapi.fileChooser.FileChooser;
26 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.vfs.LocalFileSystem;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import org.jetbrains.annotations.NotNull;
31 import org.jetbrains.annotations.Nullable;
32
33 public class CompareFilesAction extends BaseShowDiffAction {
34   public static final DataKey<DiffRequest> DIFF_REQUEST = DataKey.create("CompareFilesAction.DiffRequest");
35
36   public static final String LAST_USED_FILE_KEY = "two.files.diff.last.used.file";
37   public static final String LAST_USED_FOLDER_KEY = "two.files.diff.last.used.folder";
38
39   @Override
40   public void update(@NotNull AnActionEvent e) {
41     super.update(e);
42
43     VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
44
45     String text = "Compare Files";
46     if (files != null && files.length == 1) {
47       text = "Compare With...";
48     }
49     else if (files != null && files.length == 2) {
50       Type type1 = getType(files[0]);
51       Type type2 = getType(files[1]);
52
53       if (type1 != type2) {
54         text = "Compare";
55       }
56       else {
57         switch (type1) {
58           case FILE:
59             text = "Compare Files";
60             break;
61           case DIRECTORY:
62             text = "Compare Directories";
63             break;
64           case ARCHIVE:
65             text = "Compare Archives";
66             break;
67         }
68       }
69     }
70     e.getPresentation().setText(text);
71   }
72
73   protected boolean isAvailable(@NotNull AnActionEvent e) {
74     DiffRequest request = e.getData(DIFF_REQUEST);
75     if (request != null) {
76       return true;
77     }
78
79     VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
80     if (files == null) {
81       return false;
82     }
83
84     if (files.length == 1) {
85       return files[0].isValid();
86     }
87     else if (files.length == 2) {
88       return files[0].isValid() && files[1].isValid();
89     }
90     else {
91       return false;
92     }
93   }
94
95   @Nullable
96   @Override
97   protected DiffRequest getDiffRequest(@NotNull AnActionEvent e) {
98     Project project = e.getProject();
99     DiffRequest diffRequest = e.getData(DIFF_REQUEST);
100     if (diffRequest != null) {
101       return diffRequest;
102     }
103
104     VirtualFile[] data = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
105     if (data.length == 1) {
106       VirtualFile otherFile = getOtherFile(project, data[0]);
107       if (otherFile == null) return null;
108       if (!data[0].isValid()) return null;
109       return DiffRequestFactory.getInstance().createFromFiles(project, data[0], otherFile);
110     }
111     else {
112       return DiffRequestFactory.getInstance().createFromFiles(project, data[0], data[1]);
113     }
114   }
115
116   @Nullable
117   private static VirtualFile getOtherFile(@Nullable Project project, @NotNull VirtualFile file) {
118     FileChooserDescriptor descriptor;
119     String key;
120
121     Type type = getType(file);
122     if (type == Type.DIRECTORY || type == Type.ARCHIVE) {
123       descriptor = new FileChooserDescriptor(false, true, true, false, false, false);
124       key = LAST_USED_FOLDER_KEY;
125     }
126     else {
127       descriptor = new FileChooserDescriptor(true, false, false, true, true, false);
128       key = LAST_USED_FILE_KEY;
129     }
130     VirtualFile selectedFile = getDefaultSelection(project, key, file);
131     VirtualFile otherFile = FileChooser.chooseFile(descriptor, project, selectedFile);
132     if (otherFile != null) updateDefaultSelection(project, key, otherFile);
133     return otherFile;
134   }
135
136   @NotNull
137   private static VirtualFile getDefaultSelection(@Nullable Project project, @NotNull String key, @NotNull VirtualFile file) {
138     if (project == null) return file;
139     final String path = PropertiesComponent.getInstance(project).getValue(key);
140     if (path == null) return file;
141     VirtualFile lastSelection = LocalFileSystem.getInstance().findFileByPath(path);
142     return lastSelection != null ? lastSelection : file;
143   }
144
145   private static void updateDefaultSelection(@Nullable Project project, @NotNull String key, @NotNull VirtualFile file) {
146     if (project == null) return;
147     PropertiesComponent.getInstance(project).setValue(key, file.getPath());
148   }
149
150   @NotNull
151   private static Type getType(@Nullable VirtualFile file) {
152     if (file == null) return Type.FILE;
153     if (file.isDirectory()) return Type.DIRECTORY;
154     if (file.getFileType() instanceof ArchiveFileType) return Type.ARCHIVE;
155     return Type.FILE;
156   }
157
158   private enum Type {FILE, DIRECTORY, ARCHIVE}
159 }