vcs: migrate to AsyncChangesBrowserBase

GitOrigin-RevId: 9222564917de4ce06d30fc2d1be9557bc7f36fee
This commit is contained in:
Aleksey Pivovarov
2023-03-13 19:42:12 +00:00
committed by intellij-monorepo-bot
parent 300c8020b7
commit 68003438d1
4 changed files with 79 additions and 48 deletions
@@ -9,6 +9,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.JBPopupListener;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePath;
@@ -51,27 +53,36 @@ public abstract class PresentableGoToChangePopupAction<T> extends GoToChangePopu
return getChanges().getList().size() > 1;
}
@NotNull
private DefaultTreeModel buildTreeModel(@NotNull Project project,
@NotNull ChangesGroupingPolicyFactory grouping,
@NotNull List<? extends T> changes) {
MultiMap<ChangesBrowserNode.Tag, GenericChangesBrowserNode> groups = MultiMap.createLinked();
private class MyAsyncChangesTreeModel extends SimpleAsyncChangesTreeModel {
private final Project myProject;
private final List<? extends T> myChanges;
for (int i = 0; i < changes.size(); i++) {
PresentableChange change = getPresentation(changes.get(i));
if (change == null) continue;
FilePath filePath = change.getFilePath();
FileStatus fileStatus = change.getFileStatus();
ChangesBrowserNode.Tag tag = change.getTag();
groups.putValue(tag, new GenericChangesBrowserNode(filePath, fileStatus, i));
private MyAsyncChangesTreeModel(@NotNull Project project, @NotNull List<? extends T> changes) {
myProject = project;
myChanges = changes;
}
MyTreeModelBuilder builder = new MyTreeModelBuilder(project, grouping);
for (ChangesBrowserNode.Tag tag : groups.keySet()) {
builder.setGenericNodes(groups.get(tag), tag);
@NotNull
@Override
public DefaultTreeModel buildTreeModelSync(@NotNull ChangesGroupingPolicyFactory grouping) {
MultiMap<ChangesBrowserNode.Tag, GenericChangesBrowserNode> groups = MultiMap.createLinked();
for (int i = 0; i < myChanges.size(); i++) {
PresentableChange change = getPresentation(myChanges.get(i));
if (change == null) continue;
FilePath filePath = change.getFilePath();
FileStatus fileStatus = change.getFileStatus();
ChangesBrowserNode.Tag tag = change.getTag();
groups.putValue(tag, new GenericChangesBrowserNode(filePath, fileStatus, i));
}
MyTreeModelBuilder builder = new MyTreeModelBuilder(myProject, grouping);
for (ChangesBrowserNode.Tag tag : groups.keySet()) {
builder.setGenericNodes(groups.get(tag), tag);
}
return builder.build();
}
return builder.build();
}
protected abstract void onSelected(@NotNull T change);
@@ -97,6 +108,12 @@ public abstract class PresentableGoToChangePopupAction<T> extends GoToChangePopu
.setCancelKeyEnabled(true)
.setCancelOnClickOutside(true)
.setDimensionServiceKey(project, "Diff.GoToChangePopup", false)
.addListener(new JBPopupListener() {
@Override
public void onClosed(@NotNull LightweightWindowEvent event) {
cb.shutdown();
}
})
.createPopup());
return popup.get();
@@ -106,7 +123,7 @@ public abstract class PresentableGoToChangePopupAction<T> extends GoToChangePopu
// Helpers
//
private class MyChangesBrowser extends ChangesBrowserBase {
private class MyChangesBrowser extends AsyncChangesBrowserBase {
@NotNull private final Ref<? extends JBPopup> myRef;
@NotNull private final ListSelection<? extends T> myChanges;
@@ -117,25 +134,28 @@ public abstract class PresentableGoToChangePopupAction<T> extends GoToChangePopu
myViewer.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
init();
myViewer.rebuildTree();
AsyncChangesTree viewer = getViewer();
AsyncChangesTree.RequestId requestId = viewer.requestRefresh();
if (myChanges.getSelectedIndex() != -1) {
UiNotifyConnector.doWhenFirstShown(this, () -> {
DefaultMutableTreeNode toSelect = TreeUtil.findNode(myViewer.getRoot(), node -> {
return node instanceof GenericChangesBrowserNode &&
((GenericChangesBrowserNode)node).getIndex() == myChanges.getSelectedIndex();
viewer.invokeAfterRefresh(requestId, () -> {
DefaultMutableTreeNode toSelect = TreeUtil.findNode(myViewer.getRoot(), node -> {
return node instanceof GenericChangesBrowserNode &&
((GenericChangesBrowserNode)node).getIndex() == myChanges.getSelectedIndex();
});
if (toSelect != null) {
TreeUtil.selectNode(myViewer, toSelect);
}
});
if (toSelect != null) {
TreeUtil.selectNode(myViewer, toSelect);
}
});
}
}
@NotNull
@Override
protected DefaultTreeModel buildTreeModel() {
return PresentableGoToChangePopupAction.this.buildTreeModel(myProject, getGrouping(), myChanges.getList());
protected AsyncChangesTreeModel getChangesTreeModel() {
return new MyAsyncChangesTreeModel(myProject, myChanges.getList());
}
@NotNull
@@ -23,8 +23,11 @@ import java.awt.Component
import java.util.concurrent.CompletableFuture
import javax.swing.tree.DefaultTreeModel
class SavedPatchesChangesBrowser(project: Project, private val focusMainUi: (Component?) -> Unit,
parentDisposable: Disposable) : ChangesBrowserBase(project, false, false), Disposable {
class SavedPatchesChangesBrowser(project: Project,
private val focusMainUi: (Component?) -> Unit,
parentDisposable: Disposable)
: AsyncChangesBrowserBase(project, false, false), Disposable {
var changes: Collection<SavedPatchesProvider.ChangeObject> = emptyList()
private set
@@ -77,17 +80,19 @@ class SavedPatchesChangesBrowser(project: Project, private val focusMainUi: (Com
return super.createPopupMenuActions() + ActionManager.getInstance().getAction("Vcs.SavedPatches.ChangesBrowser.ContextMenu")
}
override fun buildTreeModel(): DefaultTreeModel {
val builder = TreeModelBuilder(myProject, grouping)
val groupedChanges = changes.groupBy { it.tag }
for ((tag, changes) in groupedChanges) {
if (changes.isEmpty()) continue
val root = if (tag == null) builder.myRoot else builder.createTagNode(tag, SimpleTextAttributes.REGULAR_ATTRIBUTES, false)
changes.forEach { change ->
builder.insertChangeNode(change.filePath, root, ChangeObjectNode(change))
override val changesTreeModel: AsyncChangesTreeModel = object : SimpleAsyncChangesTreeModel() {
override fun buildTreeModelSync(grouping: ChangesGroupingPolicyFactory): DefaultTreeModel {
val builder = TreeModelBuilder(myProject, grouping)
val groupedChanges = changes.groupBy { it.tag }
for ((tag, changes) in groupedChanges) {
if (changes.isEmpty()) continue
val root = if (tag == null) builder.myRoot else builder.createTagNode(tag, SimpleTextAttributes.REGULAR_ATTRIBUTES, false)
changes.forEach { change ->
builder.insertChangeNode(change.filePath, root, ChangeObjectNode(change))
}
}
return builder.build()
}
return builder.build()
}
private fun setEmpty(updateEmptyText: (StatusText) -> Unit) = setData(emptyList(), updateEmptyText)
@@ -186,6 +191,7 @@ class SavedPatchesChangesBrowser(project: Project, private val focusMainUi: (Com
}
override fun dispose() {
shutdown()
}
private class ChangeObjectNode(change: SavedPatchesProvider.ChangeObject) :
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultTreeModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class SimpleChangesBrowser extends ChangesBrowserBase {
@@ -30,8 +31,12 @@ public class SimpleChangesBrowser extends ChangesBrowserBase {
}
/**
* @deprecated Consider overriding {@link ChangesBrowserBase} instead.
*/
@NotNull
@Override
@Deprecated
protected DefaultTreeModel buildTreeModel() {
return TreeModelBuilder.buildFromChanges(myProject, getGrouping(), myChanges, myChangeNodeDecorator);
}
@@ -9,15 +9,12 @@ import com.intellij.openapi.vcs.changes.ChangeListAdapter;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.RemoteRevisionsCache;
import com.intellij.openapi.vcs.changes.actions.RollbackDialogAction;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserBase;
import com.intellij.openapi.vcs.changes.ui.RemoteStatusChangeNodeDecorator;
import com.intellij.openapi.vcs.changes.ui.TreeModelBuilder;
import com.intellij.openapi.vcs.changes.ui.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.update.DisposableUpdate;
import com.intellij.util.ui.update.MergingUpdateQueue;
import org.jetbrains.annotations.NotNull;
import javax.swing.tree.DefaultTreeModel;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
@@ -28,7 +25,7 @@ import java.util.Set;
* After the revert completes, the changes list is automatically refreshed according to the actual changes
* retrieved from the {@link ChangeListManager}.
*/
public class ChangesBrowserWithRollback extends ChangesBrowserBase implements Disposable {
public class ChangesBrowserWithRollback extends AsyncChangesBrowserBase implements Disposable {
private final Set<Change> myOriginalChanges;
public ChangesBrowserWithRollback(@NotNull Project project, @NotNull List<? extends Change> changes) {
@@ -45,6 +42,7 @@ public class ChangesBrowserWithRollback extends ChangesBrowserBase implements Di
@Override
public void dispose() {
shutdown();
}
@NotNull
@@ -67,12 +65,14 @@ public class ChangesBrowserWithRollback extends ChangesBrowserBase implements Di
@NotNull
@Override
protected DefaultTreeModel buildTreeModel() {
Collection<Change> allChanges = ChangeListManager.getInstance(myProject).getAllChanges();
List<Change> newChanges = ContainerUtil.filter(allChanges, myOriginalChanges::contains);
protected AsyncChangesTreeModel getChangesTreeModel() {
return SimpleAsyncChangesTreeModel.create(grouping -> {
Collection<Change> allChanges = ChangeListManager.getInstance(myProject).getAllChanges();
List<Change> newChanges = ContainerUtil.filter(allChanges, myOriginalChanges::contains);
RemoteStatusChangeNodeDecorator decorator = RemoteRevisionsCache.getInstance(myProject).getChangesNodeDecorator();
return TreeModelBuilder.buildFromChanges(myProject, getGrouping(), newChanges, decorator);
RemoteStatusChangeNodeDecorator decorator = RemoteRevisionsCache.getInstance(myProject).getChangesNodeDecorator();
return TreeModelBuilder.buildFromChanges(myProject, grouping, newChanges, decorator);
});
}