From b26786a0e98275e0f3cad373f7c8fe4f2f5b7c4d Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 5 Oct 2009 17:57:51 +0400 Subject: [PATCH] TreeUi: infinite update fix --- .../intellij/testFramework/IdeaTestUtil.java | 4 ++ .../ide/util/treeView/AbstractTreeUi.java | 38 ++++++++++++++++--- .../ide/util/treeView/UpdaterTreeState.java | 38 +++++++++++++++++-- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/java/testFramework/src/com/intellij/testFramework/IdeaTestUtil.java b/java/testFramework/src/com/intellij/testFramework/IdeaTestUtil.java index 3e1752c27ca1..32be37bcb667 100644 --- a/java/testFramework/src/com/intellij/testFramework/IdeaTestUtil.java +++ b/java/testFramework/src/com/intellij/testFramework/IdeaTestUtil.java @@ -178,6 +178,10 @@ public class IdeaTestUtil extends PlatformTestUtil { return currentLine; } + public static String print(Object[] objects) { + return print(Arrays.asList(objects)); + } + public static String print(Collection c) { StringBuilder result = new StringBuilder(); for (Iterator iterator = c.iterator(); iterator.hasNext();) { diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 2720e768d6c7..a3599b6d38c6 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -1310,6 +1310,22 @@ class AbstractTreeUi { return myNodeActions; } + public List getLoadedChildrenFor(Object element) { + List result = new ArrayList(); + + DefaultMutableTreeNode node = (DefaultMutableTreeNode)findNodeByElement(element); + if (node != null) { + for (int i = 0; i < node.getChildCount(); i++) { + TreeNode each = node.getChildAt(i); + if (isLoadingNode(each)) continue; + + result.add(getElementFor(each)); + } + } + + return result; + } + static class ElementNode extends DefaultMutableTreeNode { Set myElements = new HashSet(); @@ -1521,14 +1537,15 @@ class AbstractTreeUi { processActions(node, element, myNodeActions); - if (!isLoadedInBackground(element)) { + boolean childrenReady = !isLoadedInBackground(element); + if (childrenReady) { processActions(node, element, myNodeChildrenActions); } if (!isUpdatingParent(node) && !isWorkerBusy()) { final UpdaterTreeState state = myUpdaterState; if (myNodeActions.size() == 0 && state != null && !state.isProcessingNow()) { - if (!state.restore()) { + if (!state.restore(childrenReady ? node : null)) { setUpdaterState(state); } } @@ -1537,6 +1554,7 @@ class AbstractTreeUi { maybeReady(); } + private void processActions(DefaultMutableTreeNode node, Object element, final Map> nodeActions) { final List actions = nodeActions.get(element); if (actions != null) { @@ -1768,7 +1786,7 @@ class AbstractTreeUi { return parentElementInTree.equals(parentElement); } - private Condition getExpiredElementCondition(final Object element) { + public Condition getExpiredElementCondition(final Object element) { return new Condition() { public boolean value(final Object o) { return isInStructure(element); @@ -2423,6 +2441,12 @@ class AbstractTreeUi { runDone(onDone); return; } + + if (getRootNode() == toSelect && !myTree.isRootVisible()) { + runDone(onDone); + return; + } + final int row = myTree.getRowForPath(new TreePath(toSelect.getPath())); if (myUpdaterState != null) { @@ -2646,7 +2670,7 @@ class AbstractTreeUi { } @Nullable - private Object getElementFor(DefaultMutableTreeNode node) { + Object getElementFor(DefaultMutableTreeNode node) { if (node != null) { final Object o = node.getUserObject(); if (o instanceof NodeDescriptor) { @@ -2876,7 +2900,7 @@ class AbstractTreeUi { myTree.invalidate(); - state.restore(); + state.restore(null); } public AbstractTreeUi setClearOnHideDelay(final long clearOnHideDelay) { @@ -3055,4 +3079,8 @@ class AbstractTreeUi { return myChanges.get(desc); } } + + UpdaterTreeState getUpdaterState() { + return myUpdaterState; + } } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/UpdaterTreeState.java b/platform/platform-api/src/com/intellij/ide/util/treeView/UpdaterTreeState.java index bb6e147747b4..3e9c891572be 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/UpdaterTreeState.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/UpdaterTreeState.java @@ -2,8 +2,9 @@ package com.intellij.ide.util.treeView; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Condition; -import com.intellij.util.Function; import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -122,11 +123,31 @@ public class UpdaterTreeState { myCanRunRestore = state.myCanRunRestore; } - public boolean restore() { + public boolean restore(@Nullable DefaultMutableTreeNode actionNode) { if (isProcessingNow() || !myCanRunRestore) return false; myProcessingNow = true; + + if (actionNode != null) { + Object readyElement = myUi.getElementFor(actionNode); + if (readyElement != null) { + Iterator toSelect = myToSelect.keySet().iterator(); + while (toSelect.hasNext()) { + Object eachToSelect = toSelect.next(); + if (readyElement.equals(myUi.getTreeStructure().getParentElement(eachToSelect))) { + List children = myUi.getLoadedChildrenFor(readyElement); + if (!children.contains(eachToSelect)) { + toSelect.remove(); + if (!myToSelect.containsKey(readyElement)) { + addAdjustedSelection(eachToSelect, Condition.FALSE); + } + } + } + } + } + } + final Object[] toSelect = getToSelect(); final Object[] toExpand = getToExpand(); @@ -143,7 +164,9 @@ public class UpdaterTreeState { public void run() { processUnsuccessfulSelections(toSelect, new Function() { public Object fun(final Object o) { - addSelection(o); + if (myUi.getTree().isRootVisible() || !myUi.getTreeStructure().getRootElement().equals(o)) { + addSelection(o); + } return o; } }, originallySelected); @@ -183,7 +206,7 @@ public class UpdaterTreeState { wasFullyRejected = successfulSelections.size() == 0; } - if (wasFullyRejected) return; + if (wasFullyRejected && selected.size() > 0) return; for (Object eachToSelect : toSelect) { if (!selected.contains(eachToSelect)) { @@ -217,6 +240,13 @@ public class UpdaterTreeState { public void run() { processUnsuccessfulSelections(newSelection, new Function() { public Object fun(final Object o) { + if (myUi.isInStructure(o) && !adjusted.get(o).value(o)) { + Object parent = myUi.getTreeStructure().getParentElement(o); + if (parent != null) { + addSelection(parent); + } + return null; + } addAdjustedSelection(o, adjusted.get(o)); return null; }