[git] Fix UI freezes in git log branches tree

`SearchTreeModel#updateStructure` used to call `removeNodeFromParent` for every single node removed.
However, it makes sense to skip calls for children if parent node is removed as well.

GitOrigin-RevId: 46f9ab639bf632610b4c53157af48cc41c16abe9
This commit is contained in:
Ilia.Shulgin
2024-09-20 15:07:46 +02:00
committed by intellij-monorepo-bot
parent 7445a605ad
commit eca4592395
2 changed files with 24 additions and 10 deletions

View File

@@ -14,6 +14,7 @@ import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.Reference2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -192,17 +193,34 @@ public abstract class FilteringTree<T extends DefaultMutableTreeNode, U> {
N treeNode = myNodeCache.get(node);
newNodes.put(node, treeNode == null ? createNode(node) : treeNode);
}
List<N> oldNodes = new ArrayList<>();
for (Map.Entry<U, N> entry : myNodeCache.entrySet()) {
if (!newNodes.containsKey(entry.getKey())) oldNodes.add(entry.getValue());
}
Set<N> nodesToRemove = getNodesToRemove(newNodes);
myNodeCache = newNodes;
for (N node : oldNodes) {
for (N node : nodesToRemove) {
if (node.getParent() != null) removeNodeFromParent(node);
}
refilter();
}
private @NotNull Set<N> getNodesToRemove(Map<U, N> newNodes) {
Set<N> nodesToRemove = new ReferenceOpenHashSet<>();
for (Map.Entry<U, N> entry : myNodeCache.entrySet()) {
if (!newNodes.containsKey(entry.getKey())) {
N node = entry.getValue();
boolean shouldRemove = true;
for (TreeNode treeNode : node.getPath()) {
if (nodesToRemove.contains(treeNode)) {
shouldRemove = false;
break;
}
}
if (shouldRemove) {
nodesToRemove.add(node);
}
}
}
return nodesToRemove;
}
@Override
@SuppressWarnings("unchecked")
public N getRoot() {
@@ -251,7 +269,7 @@ public abstract class FilteringTree<T extends DefaultMutableTreeNode, U> {
}
private @NotNull Map<U, N> createUserObjectMap() {
return myUseIdentityHashing ? new IdentityHashMap<>() : new HashMap<>();
return myUseIdentityHashing ? new Reference2ObjectLinkedOpenHashMap<>() : new LinkedHashMap<>();
}
private boolean equalUserObjects(@Nullable U u1, @Nullable U u2) {

View File

@@ -33,7 +33,6 @@ import com.intellij.vcs.branch.BranchPresentation
import com.intellij.vcs.branch.LinkedBranchDataImpl
import com.intellij.vcs.log.util.VcsLogUtil
import com.intellij.vcsUtil.VcsImplUtil
import git4idea.branch.GitBranchType
import git4idea.branch.calcTooltip
import git4idea.repo.GitRepository
import git4idea.repo.GitRepositoryManager
@@ -50,7 +49,6 @@ import java.awt.Dimension
import java.awt.Graphics
import java.awt.GraphicsEnvironment
import java.awt.datatransfer.Transferable
import java.util.*
import java.util.function.Supplier
import javax.swing.JComponent
import javax.swing.JTree
@@ -400,8 +398,6 @@ internal class FilteringBranchesTree(
updateSpeedSearchBackground()
}
override fun useIdentityHashing(): Boolean = false
private fun updateSpeedSearchBackground() {
val speedSearch = searchModel.speedSearch as? SpeedSearch ?: return
val textEditor = component.searchField?.textEditor ?: return