IDEA-156485 git: allow to copy content from 'compare with branch' dialog

* Do not wait for contents to load before showing windows

GitOrigin-RevId: 7980f000e20b6d5bd2840b2dd577f9bc884ebffd
This commit is contained in:
Aleksey Pivovarov
2021-01-27 16:00:10 +00:00
committed by intellij-monorepo-bot
parent 8f506ccaeb
commit 2a83474c00
8 changed files with 264 additions and 222 deletions
@@ -90,9 +90,7 @@ compare.branches.dialog.title.branch.with.branch=Comparing {0} with {1}
compare.branches.dialog.title.branch.with.branch.in.root=Comparing {0} with {1} in root {2}
compare.branches.commits.that.exist.in.branch.but.not.in.branch.vcs.command=Commits that exist in {0} but don''t exist in {1} ({2}):
popup.title.select.branch.to.compare=Select Branch to Compare
progress.title.collecting.changes=Collecting Changes...
notification.title.couldn.t.compare.with.branch=Couldn't compare with branch
notification.message.couldn.t.compare.with.branch=Couldn''t compare {0,choice,1#file|2#directory} {1} with branch ''{2}'':\n{3}
compare.with.dialog.get.from.vcs.action.title=Get from VCS
error.text.file.not.found.in.branch={0,choice,1#File|2#Directory} {1} doesn''t exist in branch ''{2}''
dialog.message.following.repositories.already.have.specified=<html>The following repositories already have specified {0}<b>{1}</b>:<br>{2}.<br>Do you want to checkout existing {3}?
dialog.title.already.exists={0} Already Exists
@@ -24,5 +24,6 @@
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="module" module-name="intellij.platform.util.ui" />
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.diff.impl" />
</component>
</module>
@@ -0,0 +1,198 @@
// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.dvcs.actions;
import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.ui.SimpleChangesBrowser;
import com.intellij.openapi.vcs.changes.ui.browser.LoadingChangesPanel;
import com.intellij.openapi.vcs.history.actions.GetVersionAction;
import com.intellij.openapi.vcs.history.actions.GetVersionAction.FileRevisionProvider;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.StatusText;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class CompareWithLocalDialog {
public static void showDialog(@NotNull Project project,
@NotNull @NlsContexts.DialogTitle String dialogTitle,
@NotNull LocalContent localContent,
@NotNull ThrowableComputable<? extends Collection<Change>, ? extends VcsException> changesLoader) {
Disposable loadingDisposable = Disposer.newDisposable();
MyChangesBrowser changesBrowser = new MyChangesBrowser(project, localContent);
MyLoadingChangesPanel changesPanel = new MyLoadingChangesPanel(changesBrowser, loadingDisposable) {
@NotNull
@Override
protected Collection<Change> loadChanges() throws VcsException {
return changesLoader.compute();
}
};
changesPanel.reloadChanges();
DialogBuilder dialogBuilder = new DialogBuilder(project);
dialogBuilder.setTitle(dialogTitle);
dialogBuilder.setActionDescriptors(new DialogBuilder.CloseDialogAction());
dialogBuilder.setCenterPanel(changesPanel);
dialogBuilder.setPreferredFocusComponent(changesPanel.getChangesBrowser().getPreferredFocusedComponent());
dialogBuilder.addDisposable(loadingDisposable);
dialogBuilder.setDimensionServiceKey("Git.DiffForPathsDialog");
dialogBuilder.showNotModal();
}
private static abstract class MyLoadingChangesPanel extends JPanel implements DataProvider {
public static final DataKey<MyLoadingChangesPanel> DATA_KEY = DataKey.create("git4idea.log.MyLoadingChangesPanel");
private final SimpleChangesBrowser myChangesBrowser;
private final LoadingChangesPanel myLoadingPanel;
private MyLoadingChangesPanel(@NotNull SimpleChangesBrowser changesBrowser, @NotNull Disposable disposable) {
super(new BorderLayout());
myChangesBrowser = changesBrowser;
StatusText emptyText = myChangesBrowser.getViewer().getEmptyText();
myLoadingPanel = new LoadingChangesPanel(myChangesBrowser, emptyText, disposable);
add(myLoadingPanel, BorderLayout.CENTER);
}
@NotNull
public SimpleChangesBrowser getChangesBrowser() {
return myChangesBrowser;
}
public void reloadChanges() {
myLoadingPanel.loadChangesInBackground(this::loadChanges, this::applyResult);
}
@NotNull
protected abstract Collection<Change> loadChanges() throws VcsException;
private void applyResult(@Nullable Collection<Change> changes) {
myChangesBrowser.setChangesToDisplay(changes != null ? changes : Collections.emptyList());
}
@Nullable
@Override
public Object getData(@NotNull String dataId) {
if (DATA_KEY.is(dataId)) {
return this;
}
return null;
}
}
private static class MyChangesBrowser extends SimpleChangesBrowser {
@NotNull private final CompareWithLocalDialog.LocalContent myLocalContent;
private MyChangesBrowser(@NotNull Project project, @NotNull LocalContent localContent) {
super(project, false, true);
myLocalContent = localContent;
}
@NotNull
@Override
protected List<AnAction> createToolbarActions() {
return ContainerUtil.append(
super.createToolbarActions(),
new MyGetVersionAction()
);
}
@NotNull
@Override
protected List<AnAction> createPopupMenuActions() {
return ContainerUtil.append(
super.createPopupMenuActions(),
new MyGetVersionAction()
);
}
}
private static class MyGetVersionAction extends DumbAwareAction {
private MyGetVersionAction() {
super(VcsBundle.messagePointer("action.name.get.file.content.from.repository"),
VcsBundle.messagePointer("action.description.get.file.content.from.repository"), AllIcons.Actions.Download);
}
@Override
public void update(@NotNull AnActionEvent e) {
Project project = e.getProject();
MyLoadingChangesPanel changesPanel = e.getData(MyLoadingChangesPanel.DATA_KEY);
if (project == null || changesPanel == null) {
e.getPresentation().setEnabledAndVisible(false);
return;
}
MyChangesBrowser browser = ObjectUtils.tryCast(changesPanel.getChangesBrowser(), MyChangesBrowser.class);
boolean isVisible = browser != null && browser.myLocalContent != LocalContent.NONE;
boolean isEnabled = isVisible && !browser.getSelectedChanges().isEmpty();
e.getPresentation().setVisible(isVisible);
e.getPresentation().setEnabled(isEnabled);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = Objects.requireNonNull(e.getProject());
MyLoadingChangesPanel changesPanel = e.getRequiredData(MyLoadingChangesPanel.DATA_KEY);
MyChangesBrowser browser = (MyChangesBrowser)changesPanel.getChangesBrowser();
List<FileRevisionProvider> fileContentProviders = ContainerUtil.map(changesPanel.getChangesBrowser().getSelectedChanges(), change -> {
return new MyFileContentProvider(change, browser.myLocalContent);
});
GetVersionAction.doGet(project, DvcsBundle.message("compare.with.dialog.get.from.vcs.action.title"), fileContentProviders,
() -> changesPanel.reloadChanges());
}
private static class MyFileContentProvider implements FileRevisionProvider {
@NotNull private final Change myChange;
@NotNull private final CompareWithLocalDialog.LocalContent myLocalContent;
private MyFileContentProvider(@NotNull Change change,
@NotNull LocalContent localContent) {
myChange = change;
myLocalContent = localContent;
}
@NotNull
@Override
public FilePath getFilePath() {
return ChangesUtil.getFilePath(myChange);
}
@Override
public byte @Nullable [] getContent() throws VcsException {
ContentRevision revision = myLocalContent == LocalContent.AFTER ? myChange.getBeforeRevision()
: myChange.getAfterRevision();
if (revision == null) return null;
return ChangesUtil.loadContentRevision(revision);
}
}
}
public enum LocalContent {BEFORE, AFTER, NONE}
}
@@ -1,23 +1,31 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.dvcs.actions;
import com.intellij.diff.DiffDialogHints;
import com.intellij.diff.DiffManager;
import com.intellij.diff.chains.DiffRequestChain;
import com.intellij.diff.chains.DiffRequestProducerException;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.dvcs.repo.AbstractRepositoryManager;
import com.intellij.dvcs.repo.Repository;
import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.ListSelection;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsNotifier;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.actions.diff.ChangeDiffRequestProducer;
import com.intellij.openapi.vcs.changes.ui.ChangeDiffRequestChain;
import com.intellij.openapi.vcs.history.VcsDiffUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.JBIterable;
@@ -25,11 +33,8 @@ import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.*;
import static com.intellij.openapi.vcs.VcsNotificationIdsHolder.COULD_NOT_COMPARE_WITH_BRANCH;
import static com.intellij.util.ObjectUtils.chooseNotNull;
/**
@@ -88,32 +93,38 @@ public abstract class DvcsCompareWithBranchAction<T extends Repository> extends
@NotNull final VirtualFile file,
@NotNull final @NlsSafe String head,
@NotNull final @NlsSafe String compare) {
new Task.Backgroundable(project, DvcsBundle.message("progress.title.collecting.changes"), true) {
private Collection<Change> changes;
FilePath filePath = VcsUtil.getFilePath(file);
String revNumTitle1 = VcsDiffUtil.getRevisionTitle(compare, false);
String revNumTitle2 = VcsDiffUtil.getRevisionTitle(head, true);
@Override
public void run(@NotNull ProgressIndicator indicator) {
try {
changes = getDiffChanges(project, file, compare);
}
catch (VcsException e) {
VcsNotifier.getInstance(project).notifyImportantWarning(
COULD_NOT_COMPARE_WITH_BRANCH,
DvcsBundle.message("notification.title.couldn.t.compare.with.branch"),
DvcsBundle.message("notification.message.couldn.t.compare.with.branch",
file.isDirectory() ? 1 : 0, file.getPresentableUrl(), compare, e.getMessage()));
}
}
if (file.isDirectory()) {
String dialogTitle = VcsBundle.message("history.dialog.title.difference.between.versions.in",
revNumTitle1, revNumTitle2, filePath.getName());
CompareWithLocalDialog.showDialog(project, dialogTitle, CompareWithLocalDialog.LocalContent.AFTER, () -> {
return getDiffChanges(project, file, compare);
});
}
else {
DiffRequestChain requestChain = new ChangeDiffRequestChain.Async() {
@Override
protected @NotNull ListSelection<ChangeDiffRequestProducer> loadRequestProducers() throws DiffRequestProducerException {
try {
Collection<Change> changes = getDiffChanges(project, file, compare);
@Override
public void onSuccess() {
//if changes null -> then exception occurred before
if (changes != null) {
VcsDiffUtil.showDiffFor(project, changes, VcsDiffUtil.getRevisionTitle(compare, false), VcsDiffUtil.getRevisionTitle(head, true),
VcsUtil.getFilePath(file));
Map<Key<?>, Object> changeContext = new HashMap<>(2);
changeContext.put(DiffUserDataKeysEx.VCS_DIFF_LEFT_CONTENT_TITLE, revNumTitle1);
changeContext.put(DiffUserDataKeysEx.VCS_DIFF_RIGHT_CONTENT_TITLE, revNumTitle2);
return ListSelection.createAt(new ArrayList<>(changes), 0)
.map(change -> ChangeDiffRequestProducer.create(project, change, changeContext));
}
catch (VcsException e) {
throw new DiffRequestProducerException(e);
}
}
}
}.queue();
};
DiffManager.getInstance().showDiff(project, requestChain, DiffDialogHints.DEFAULT);
}
}
@NlsSafe
@@ -69,4 +69,15 @@ public class ShowDiffContext {
if (!myRequestContext.containsKey(change)) myRequestContext.put(change, new HashMap<>());
myRequestContext.get(change).put(key, value);
}
@NotNull
public static ShowDiffContext createStaticChangeContext(@NotNull Map<Key<?>, Object> map) {
return new ShowDiffContext() {
@NotNull
@Override
public Map<Key<?>, Object> getChangeContext(@NotNull Change change) {
return map;
}
};
}
}
@@ -47,7 +47,9 @@ public final class VcsDiffUtil {
@NotNull @Nls String revNumTitle2,
@NotNull FilePath filePath) {
if (filePath.isDirectory()) {
showChangesDialog(project, getDialogTitle(filePath, revNumTitle1, revNumTitle2), new ArrayList<>(changes));
String dialogTitle = VcsBundle.message("history.dialog.title.difference.between.versions.in",
revNumTitle1, revNumTitle2, filePath.getName());
showChangesDialog(project, dialogTitle, new ArrayList<>(changes));
}
else {
if (changes.isEmpty()) {
@@ -57,27 +59,12 @@ public final class VcsDiffUtil {
Map<Key<?>, Object> revTitlesMap = new HashMap<>(2);
revTitlesMap.put(VCS_DIFF_LEFT_CONTENT_TITLE, revNumTitle1);
revTitlesMap.put(VCS_DIFF_RIGHT_CONTENT_TITLE, revNumTitle2);
ShowDiffContext showDiffContext = new ShowDiffContext() {
@NotNull
@Override
public Map<Key<?>, Object> getChangeContext(@NotNull Change change) {
return revTitlesMap;
}
};
ShowDiffContext showDiffContext = ShowDiffContext.createStaticChangeContext(revTitlesMap);
ShowDiffAction.showDiffForChange(project, changes, 0, showDiffContext);
}
}
}
@NotNull
private static @NlsContexts.DialogTitle String getDialogTitle(@NotNull final FilePath filePath, @NotNull final String revNumTitle1,
@NotNull final String revNumTitle2) {
return VcsBundle.message("history.dialog.title.difference.between.versions.in",
revNumTitle1,
revNumTitle2,
filePath.getName());
}
@Nls
@NotNull
public static String getRevisionTitle(@NotNull @NlsSafe String revision, boolean localMark) {
@@ -944,7 +944,6 @@ git.log.diff.handler.failed.message={0} failed
git.log.diff.handler.paths.diff.title=Changes Between {0} and {1} in {2}
git.log.diff.handler.local.version.name=local version
git.log.diff.handler.local.version.content.title=Local
git.log.diff.handler.get.from.vcs.title=Get from VCS
git.log.refGroup.local=Local
@@ -11,33 +11,15 @@ import com.intellij.diff.chains.SimpleDiffRequestProducer;
import com.intellij.diff.contents.DiffContent;
import com.intellij.diff.contents.EmptyContent;
import com.intellij.diff.requests.SimpleDiffRequest;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.dvcs.actions.CompareWithLocalDialog;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.ui.SimpleChangesBrowser;
import com.intellij.openapi.vcs.changes.ui.browser.LoadingChangesPanel;
import com.intellij.openapi.vcs.history.actions.GetVersionAction;
import com.intellij.openapi.vcs.history.actions.GetVersionAction.FileRevisionProvider;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.StatusText;
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsLogDiffHandler;
@@ -53,13 +35,9 @@ import git4idea.util.GitFileUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static com.intellij.diff.DiffRequestFactoryImpl.*;
import static com.intellij.util.ObjectUtils.chooseNotNull;
@@ -136,30 +114,14 @@ public class GitLogDiffHandler implements VcsLogDiffHandler {
rightRevisionTitle,
getTitleForPaths(root, affectedPaths));
Disposable loadingDisposable = Disposer.newDisposable();
MyChangesBrowser changesBrowser = new MyChangesBrowser(myProject, isWithLocal);
MyLoadingChangesPanel changesPanel = new MyLoadingChangesPanel(changesBrowser, loadingDisposable) {
@NotNull
@Override
protected Collection<Change> loadChanges() throws VcsException {
if (isWithLocal) {
return GitChangeUtils.getDiffWithWorkingDir(myProject, root, leftRevision.asString(), filePaths, false);
}
else {
return GitChangeUtils.getDiff(myProject, root, leftRevision.asString(), rightRevision.asString(), filePaths);
}
CompareWithLocalDialog.showDialog(myProject, dialogTitle, CompareWithLocalDialog.LocalContent.AFTER, () -> {
if (isWithLocal) {
return GitChangeUtils.getDiffWithWorkingDir(myProject, root, leftRevision.asString(), filePaths, false);
}
};
changesPanel.reloadChanges();
DialogBuilder dialogBuilder = new DialogBuilder(myProject);
dialogBuilder.setTitle(dialogTitle);
dialogBuilder.setActionDescriptors(new DialogBuilder.CloseDialogAction());
dialogBuilder.setCenterPanel(changesPanel);
dialogBuilder.setPreferredFocusComponent(changesPanel.getChangesBrowser().getPreferredFocusedComponent());
dialogBuilder.addDisposable(loadingDisposable);
dialogBuilder.setDimensionServiceKey("Git.DiffForPathsDialog");
dialogBuilder.showNotModal();
else {
return GitChangeUtils.getDiff(myProject, root, leftRevision.asString(), rightRevision.asString(), filePaths);
}
});
});
}
@@ -224,129 +186,4 @@ public class GitLogDiffHandler implements VcsLogDiffHandler {
GitRevisionNumber revisionNumber = new GitRevisionNumber(hash.asString());
return GitContentRevision.createRevision(filePath, revisionNumber, myProject);
}
private static abstract class MyLoadingChangesPanel extends JPanel implements DataProvider {
public static final DataKey<MyLoadingChangesPanel> DATA_KEY = DataKey.create("git4idea.log.MyLoadingChangesPanel");
private final SimpleChangesBrowser myChangesBrowser;
private final LoadingChangesPanel myLoadingPanel;
private MyLoadingChangesPanel(@NotNull SimpleChangesBrowser changesBrowser, @NotNull Disposable disposable) {
super(new BorderLayout());
myChangesBrowser = changesBrowser;
StatusText emptyText = myChangesBrowser.getViewer().getEmptyText();
myLoadingPanel = new LoadingChangesPanel(myChangesBrowser, emptyText, disposable);
add(myLoadingPanel, BorderLayout.CENTER);
}
@NotNull
public SimpleChangesBrowser getChangesBrowser() {
return myChangesBrowser;
}
public void reloadChanges() {
myLoadingPanel.loadChangesInBackground(this::loadChanges, this::applyResult);
}
@NotNull
protected abstract Collection<Change> loadChanges() throws VcsException;
private void applyResult(@Nullable Collection<Change> changes) {
myChangesBrowser.setChangesToDisplay(changes != null ? changes : Collections.emptyList());
}
@Nullable
@Override
public Object getData(@NotNull String dataId) {
if (DATA_KEY.is(dataId)) {
return this;
}
return null;
}
}
private static class MyChangesBrowser extends SimpleChangesBrowser {
public final boolean myIsWithLocal;
private MyChangesBrowser(@NotNull Project project, boolean isWithLocal) {
super(project, false, true);
myIsWithLocal = isWithLocal;
}
@NotNull
@Override
protected List<AnAction> createToolbarActions() {
return ContainerUtil.append(
super.createToolbarActions(),
new MyGetVersionAction()
);
}
@NotNull
@Override
protected List<AnAction> createPopupMenuActions() {
return ContainerUtil.append(
super.createPopupMenuActions(),
new MyGetVersionAction()
);
}
}
private static class MyGetVersionAction extends DumbAwareAction {
private MyGetVersionAction() {
super(VcsBundle.messagePointer("action.name.get.file.content.from.repository"),
VcsBundle.messagePointer("action.description.get.file.content.from.repository"), AllIcons.Actions.Download);
}
@Override
public void update(@NotNull AnActionEvent e) {
Project project = e.getProject();
MyLoadingChangesPanel changesPanel = e.getData(MyLoadingChangesPanel.DATA_KEY);
if (project == null || changesPanel == null) {
e.getPresentation().setEnabledAndVisible(false);
return;
}
MyChangesBrowser browser = ObjectUtils.tryCast(changesPanel.getChangesBrowser(), MyChangesBrowser.class);
boolean isVisible = browser != null && browser.myIsWithLocal;
boolean isEnabled = isVisible && !browser.getSelectedChanges().isEmpty();
e.getPresentation().setVisible(isVisible);
e.getPresentation().setEnabled(isEnabled);
}
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = Objects.requireNonNull(e.getProject());
MyLoadingChangesPanel changesPanel = e.getRequiredData(MyLoadingChangesPanel.DATA_KEY);
List<FileRevisionProvider> fileContentProviders = ContainerUtil.map(changesPanel.getChangesBrowser().getSelectedChanges(),
MyFileContentProvider::new);
GetVersionAction.doGet(project, GitBundle.message("git.log.diff.handler.get.from.vcs.title"), fileContentProviders,
() -> changesPanel.reloadChanges());
}
private static class MyFileContentProvider implements FileRevisionProvider {
@NotNull private final Change myChange;
private MyFileContentProvider(@NotNull Change change) {
myChange = change;
}
@NotNull
@Override
public FilePath getFilePath() {
return ChangesUtil.getFilePath(myChange);
}
@Override
public byte @Nullable [] getContent() throws VcsException {
ContentRevision revision = myChange.getBeforeRevision();
if (revision == null) return null;
return ChangesUtil.loadContentRevision(revision);
}
}
}
}