blob: 8a16ba6a481f5382deabb22c71a4c754560af5a9 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.vcs.history;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowser;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author Konstantin Kolosovsky.
*/
public abstract class BaseDiffFromHistoryHandler<T extends VcsFileRevision> implements DiffFromHistoryHandler {
private static final Logger LOG = Logger.getInstance(BaseDiffFromHistoryHandler.class);
@NotNull protected final Project myProject;
protected BaseDiffFromHistoryHandler(@NotNull Project project) {
myProject = project;
}
@Override
public void showDiffForOne(@NotNull AnActionEvent e,
@NotNull FilePath filePath,
@NotNull VcsFileRevision previousRevision,
@NotNull VcsFileRevision revision) {
doShowDiff(filePath, previousRevision, revision, false);
}
@Override
public void showDiffForTwo(@NotNull FilePath filePath, @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
doShowDiff(filePath, revision1, revision2, true);
}
@SuppressWarnings("unchecked")
protected void doShowDiff(@NotNull FilePath filePath,
@NotNull VcsFileRevision revision1,
@NotNull VcsFileRevision revision2,
boolean autoSort) {
if (!filePath.isDirectory()) {
VcsHistoryUtil.showDifferencesInBackground(myProject, filePath, revision1, revision2, autoSort);
}
else if (revision1.equals(VcsFileRevision.NULL)) {
T right = (T)revision2;
showAffectedChanges(filePath, right);
}
else if (revision2 instanceof CurrentRevision) {
T left = (T)revision1;
showChangesBetweenRevisions(filePath, left, null);
}
else {
T left = (T)revision1;
T right = (T)revision2;
if (autoSort) {
Couple<VcsFileRevision> pair = VcsHistoryUtil.sortRevisions(revision1, revision2);
left = (T)pair.first;
right = (T)pair.second;
}
showChangesBetweenRevisions(filePath, left, right);
}
}
protected void showChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
new CollectChangesTask("Comparing revisions...") {
@NotNull
@Override
public List<Change> getChanges() throws VcsException {
return getChangesBetweenRevisions(path, rev1, rev2);
}
@NotNull
@Override
public String getDialogTitle() {
return getChangesBetweenRevisionsDialogTitle(path, rev1, rev2);
}
}.queue();
}
protected void showAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) {
new CollectChangesTask("Collecting affected changes...") {
@NotNull
@Override
public List<Change> getChanges() throws VcsException {
return getAffectedChanges(path, rev);
}
@NotNull
@Override
public String getDialogTitle() {
return getAffectedChangesDialogTitle(path, rev);
}
}.queue();
}
// rev2 == null -> compare rev1 with local
// rev2 != null -> compare rev1 with rev2
@NotNull
protected abstract List<Change> getChangesBetweenRevisions(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2)
throws VcsException;
@NotNull
protected abstract List<Change> getAffectedChanges(@NotNull final FilePath path, @NotNull final T rev) throws VcsException;
@NotNull
protected abstract String getPresentableName(@NotNull T revision);
protected void showChangesDialog(@NotNull String title, @NotNull List<Change> changes) {
DialogBuilder dialogBuilder = new DialogBuilder(myProject);
dialogBuilder.setTitle(title);
dialogBuilder.setActionDescriptors(new DialogBuilder.ActionDescriptor[]{new DialogBuilder.CloseDialogAction()});
final ChangesBrowser changesBrowser =
new ChangesBrowser(myProject, null, changes, null, false, true, null, ChangesBrowser.MyUseCase.COMMITTED_CHANGES, null);
changesBrowser.setChangesToDisplay(changes);
dialogBuilder.setCenterPanel(changesBrowser);
dialogBuilder.showNotModal();
}
protected void showError(@NotNull VcsException e, @NotNull String logMessage) {
LOG.info(logMessage, e);
VcsBalloonProblemNotifier.showOverVersionControlView(myProject, e.getMessage(), MessageType.ERROR);
}
@NotNull
protected String getChangesBetweenRevisionsDialogTitle(@NotNull final FilePath path, @NotNull final T rev1, @Nullable final T rev2) {
String rev1Title = getPresentableName(rev1);
return rev2 != null
? String.format("Difference between %s and %s in %s", rev1Title, getPresentableName(rev2), path.getName())
: String.format("Difference between %s and local version in %s", rev1Title, path.getName());
}
@NotNull
protected String getAffectedChangesDialogTitle(@NotNull final FilePath path, @NotNull final T rev) {
return String.format("Initial commit %s in %s", getPresentableName(rev), path.getName());
}
protected abstract class CollectChangesTask extends Task.Backgroundable {
private List<Change> myChanges;
public CollectChangesTask(@NotNull String title) {
super(BaseDiffFromHistoryHandler.this.myProject, title);
}
@Override
public void run(@NotNull ProgressIndicator indicator) {
try {
myChanges = getChanges();
}
catch (VcsException e) {
showError(e, "Error during task: " + getDialogTitle());
}
}
@NotNull
public abstract List<Change> getChanges() throws VcsException;
@NotNull
public abstract String getDialogTitle();
@Override
public void onSuccess() {
showChangesDialog(getDialogTitle(), ContainerUtil.notNullize(myChanges));
}
}
}