diff --git a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java index 76fe7cb15c7a..316826d8f78d 100644 --- a/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java +++ b/java/java-impl/src/com/intellij/ide/favoritesTreeView/smartPointerPsiNodes/ClassSmartPointerNode.java @@ -66,6 +66,10 @@ public class ClassSmartPointerNode extends BaseSmartPointerPsiNode{ return treeNodes; } + public boolean isAlwaysLeaf() { + return !getSettings().isShowMembers(); + } + public void updateImpl(PresentationData data) { final PsiClass aClass = getValue(); if (aClass != null) { diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFieldNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFieldNode.java index 7713af9f7dec..7a36b4fca93f 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFieldNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiFieldNode.java @@ -50,6 +50,10 @@ public class PsiFieldNode extends BasePsiMemberNode{ return 70; } + public boolean isAlwaysLeaf() { + return true; + } + @Override public String getTitle() { final PsiField field = getValue(); diff --git a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiMethodNode.java b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiMethodNode.java index 6eae9464eded..d22f5924a98d 100644 --- a/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiMethodNode.java +++ b/java/java-impl/src/com/intellij/ide/projectView/impl/nodes/PsiMethodNode.java @@ -48,6 +48,10 @@ public class PsiMethodNode extends BasePsiMemberNode{ data.setPresentableText(name); } + public boolean isAlwaysLeaf() { + return true; + } + public boolean isConstructor() { final PsiMethod psiMethod = getValue(); return psiMethod != null && psiMethod.isConstructor(); diff --git a/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java b/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java index b2a4ad9415ae..483c7f686669 100644 --- a/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java +++ b/platform/lang-api/src/com/intellij/ide/projectView/ProjectViewNode.java @@ -204,4 +204,8 @@ public abstract class ProjectViewNode extends AbstractTreeNode { update(); return getValue() != null; } + + public boolean isAlwaysLeaf() { + return false; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectTreeStructure.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectTreeStructure.java index bce1db6a3e18..6d6839ec8620 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectTreeStructure.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectTreeStructure.java @@ -16,6 +16,7 @@ package com.intellij.ide.projectView.impl; +import com.intellij.ide.projectView.ProjectViewNode; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode; import com.intellij.ide.util.treeView.AbstractTreeNode; @@ -53,4 +54,12 @@ public abstract class AbstractProjectTreeStructure extends ProjectAbstractTreeSt return false; } + public boolean isAlwaysLeaf(Object element) { + if (element instanceof ProjectViewNode) { + return ((ProjectViewNode)element).isAlwaysLeaf(); + } + else { + return super.isAlwaysLeaf(element); + } + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java index ffb1cf174eba..12d9b6fb4695 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectTreeBuilder.java @@ -90,9 +90,6 @@ public class ProjectTreeBuilder extends BaseProjectTreeBuilder { myProblemListener = new MyProblemListener(); WolfTheProblemSolver.getInstance(project).addProblemListener(myProblemListener); - //todo: kirillk turn into a real test - setCanYieldUpdate(!ApplicationManager.getApplication().isUnitTestMode()); - initRootNode(); } 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 5f2bcc3e7da6..cf80069f8176 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 @@ -914,11 +914,45 @@ public class AbstractTreeUi { private boolean processAlwaysLeaf(DefaultMutableTreeNode node) { Object element = getElementFor(node); + NodeDescriptor desc = getDescriptorFrom(node); + + if (desc == null) return false; + if (getTreeStructure().isAlwaysLeaf(element)) { removeLoading(node, true); + + if (node.getChildCount() > 0) { + final TreeNode[] children = new TreeNode[node.getChildCount()]; + for (int i = 0; i < node.getChildCount(); i++) { + children[i] = node.getChildAt(i); + } + + if (isSelectionInside(node)) { + addSelectionPath(getPathFor(node), true, Condition.TRUE); + } + + doWithUpdaterState(new Runnable() { + public void run() { + for (TreeNode each : children) { + removeNodeFromParent((MutableTreeNode)each, true); + disposeNode((DefaultMutableTreeNode)each); + } + } + }); + } + + removeFromUnbuilt(node); + desc.setWasDeclaredAlwaysLeaf(true); processNodeActionsIfReady(node); return true; } else { + boolean wasLeaf = desc.isWasDeclaredAlwaysLeaf(); + desc.setWasDeclaredAlwaysLeaf(false); + + if (wasLeaf) { + insertLoadingNode(node, true); + } + return false; } } @@ -3449,16 +3483,6 @@ public class AbstractTreeUi { node.removeAllChildren(); myTreeModel.nodeStructureChanged(node); } - - private boolean isSelectionInside(DefaultMutableTreeNode parent) { - TreePath path = new TreePath(myTreeModel.getPathToRoot(parent)); - TreePath[] paths = myTree.getSelectionPaths(); - if (paths == null) return false; - for (TreePath path1 : paths) { - if (path.isDescendant(path1)) return true; - } - return false; - } } private void maybeUpdateSubtreeToUpdate(final DefaultMutableTreeNode subtreeRoot) { @@ -3479,6 +3503,16 @@ public class AbstractTreeUi { } } + private boolean isSelectionInside(DefaultMutableTreeNode parent) { + TreePath path = new TreePath(myTreeModel.getPathToRoot(parent)); + TreePath[] paths = myTree.getSelectionPaths(); + if (paths == null) return false; + for (TreePath path1 : paths) { + if (path.isDescendant(path1)) return true; + } + return false; + } + public boolean isInStructure(@Nullable Object element) { Object eachParent = element; while (eachParent != null) { diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/NodeDescriptor.java b/platform/platform-api/src/com/intellij/ide/util/treeView/NodeDescriptor.java index 33ee8da5073b..89faab481dbd 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/NodeDescriptor.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/NodeDescriptor.java @@ -35,6 +35,8 @@ public abstract class NodeDescriptor { private long myChildrenSortingStamp = -1; private long myUpdateCount; + private boolean myWasDeclaredAlwaysLeaf; + public NodeDescriptor(Project project, NodeDescriptor parentDescriptor) { myProject = project; myParentDescriptor = parentDescriptor; @@ -105,6 +107,14 @@ public abstract class NodeDescriptor { myUpdateCount = updateCount; } + public boolean isWasDeclaredAlwaysLeaf() { + return myWasDeclaredAlwaysLeaf; + } + + public void setWasDeclaredAlwaysLeaf(boolean leaf) { + myWasDeclaredAlwaysLeaf = leaf; + } + public abstract static class NodeComparator implements Comparator { private long myStamp;