From 0afe0bc522da2324f9662a2283130bea7b6c7d2e Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Wed, 3 Mar 2010 17:21:18 +0300 Subject: [PATCH 1/2] StructureView: selectIn fixed after tree had beed made asynchronous --- .../ide/impl/StructureViewWrapperImpl.java | 44 +++++++--- .../impl/StructureViewComposite.java | 1 + .../StructureViewComponent.java | 81 +++++++------------ .../ide/structureView/StructureView.java | 1 + .../ide/util/treeView/AbstractTreeUi.java | 3 +- .../util/ui/update/MergingUpdateQueue.java | 4 + .../structure/DomStructureViewBuilder.java | 6 +- 7 files changed, 75 insertions(+), 65 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java index 386c9276fe35..52c6bc49fb2c 100644 --- a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java @@ -43,7 +43,6 @@ import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; import com.intellij.psi.PsiDocumentManager; -import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; @@ -74,6 +73,8 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl // Constructor // ------------------------------------------------------------------------- + private Runnable myPendingSelection; + public StructureViewWrapperImpl(Project project) { myProject = project; myPanel = new ContentPanel(); @@ -140,17 +141,34 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl rebuild(); } - public boolean selectCurrentElement(FileEditor fileEditor, VirtualFile file, boolean requestFocus) { - if (myStructureView != null) { - if (!Comparing.equal(myStructureView.getFileEditor(), fileEditor)) { - myFile = file; - rebuild(); + public boolean selectCurrentElement(final FileEditor fileEditor, final VirtualFile file, final boolean requestFocus) { + //todo [kirillk] + // this is dirty hack since some bright minds decided to used different TreeUi every time, so selection may be followed + // by rebuild on completely different instance of TreeUi + + Runnable runnable = new Runnable() { + public void run() { + if (myStructureView != null) { + if (!Comparing.equal(myStructureView.getFileEditor(), fileEditor)) { + myFile = file; + rebuild(); + } + myStructureView.navigateToSelectedElement(requestFocus); + } } - return myStructureView.navigateToSelectedElement(requestFocus); - } - else { - return false; + }; + + if (isStructureViewShowing()) { + if (myUpdateQueue.isEmpty()) { + runnable.run(); + } else { + myPendingSelection = runnable; + } + } else { + myPendingSelection = runnable; } + + return true; } private void scheduleRebuild() { @@ -243,6 +261,12 @@ public class StructureViewWrapperImpl implements StructureViewWrapper, Disposabl myPanel.validate(); myPanel.repaint(); + + if (myPendingSelection != null) { + Runnable selection = myPendingSelection; + myPendingSelection = null; + selection.run(); + } } @Nullable diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java index 9bde0747f516..2928ac34fcce 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewComposite.java @@ -114,4 +114,5 @@ public class StructureViewComposite implements StructureView { public StructureViewModel getTreeModel() { return getSelectedStructureView().getTreeModel(); } + } diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java index a85871cbb732..3bf989336993 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java @@ -24,7 +24,6 @@ import com.intellij.ide.structureView.*; import com.intellij.ide.structureView.impl.StructureViewFactoryImpl; import com.intellij.ide.structureView.impl.StructureViewState; import com.intellij.ide.structureView.impl.common.PsiTreeElementBase; -import com.intellij.ide.ui.customization.CustomActionsSchema; import com.intellij.ide.ui.customization.CustomizationUtil; import com.intellij.ide.util.treeView.*; import com.intellij.ide.util.treeView.smartTree.*; @@ -37,10 +36,8 @@ import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.ModificationTracker; +import com.intellij.openapi.util.*; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.pom.Navigatable; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -402,59 +399,40 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre return myFileEditor; } - public DefaultMutableTreeNode expandPathToElement(Object element) { - if (myAbstractTreeBuilder == null) return null; + public AsyncResult expandPathToElement(Object element) { + if (myAbstractTreeBuilder == null) return new AsyncResult.Rejected(); ArrayList pathToElement = getPathToElement(element); + if (pathToElement.isEmpty()) return new AsyncResult.Rejected(); - if (pathToElement.isEmpty()) return null; + final AsyncResult result = new AsyncResult(); + final AbstractTreeNode toExpand = pathToElement.get(pathToElement.size() - 1); + myAbstractTreeBuilder.expand(toExpand, new Runnable() { + public void run() { + result.setDone(toExpand); + } + }); - JTree tree = myAbstractTreeBuilder.getTree(); - - if (pathToElement.size() == 1) { - return (DefaultMutableTreeNode)tree.getModel().getRoot(); - } - - DefaultMutableTreeNode currentTreeNode = (DefaultMutableTreeNode)tree.getModel().getRoot(); - pathToElement.remove(0); - DefaultMutableTreeNode result = null; - while (currentTreeNode != null) { - AbstractTreeNode topPathElement; - if (!pathToElement.isEmpty()) { - topPathElement = pathToElement.get(0); - pathToElement.remove(0); - } - else { - topPathElement = null; - } - TreePath treePath = new TreePath(currentTreeNode.getPath()); - if (!tree.isExpanded(treePath)) { - tree.expandPath(treePath); - } - if (topPathElement != null) { - currentTreeNode = findInChildren(currentTreeNode, topPathElement); - result = currentTreeNode; - } - else { - currentTreeNode = null; - } - } return result; } - public boolean select(Object element, boolean requestFocus) { - DefaultMutableTreeNode currentTreeNode = expandPathToElement(element); - - if (currentTreeNode != null) { - TreeUtil.selectInTree(currentTreeNode, requestFocus, getTree()); - myAutoScrollToSourceHandler.setShouldAutoScroll(false); - TreePath path = new TreePath(currentTreeNode.getPath()); - TreeUtil.showRowCentered(getTree(), getTree().getRowForPath(path), false); - myAutoScrollToSourceHandler.setShouldAutoScroll(true); - centerSelectedRow(); - return true; - } - return false; + public boolean select(final Object element, final boolean requestFocus) { + myAbstractTreeBuilder.getReady(this).doWhenDone(new Runnable() { + public void run() { + expandPathToElement(element).doWhenDone(new AsyncResult.Handler() { + public void run(AbstractTreeNode abstractTreeNode) { + myAbstractTreeBuilder.select(abstractTreeNode, new Runnable() { + public void run() { + if (requestFocus) { + IdeFocusManager.getInstance(myProject).requestFocus(myAbstractTreeBuilder.getTree(), false); + } + } + }); + } + }); + } + }); + return true; } private ArrayList getPathToElement(Object element) { @@ -826,4 +804,5 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre public String getHelpID() { return ourHelpID; } + } diff --git a/platform/platform-api/src/com/intellij/ide/structureView/StructureView.java b/platform/platform-api/src/com/intellij/ide/structureView/StructureView.java index ac0f529b4f08..647dfc0691fa 100644 --- a/platform/platform-api/src/com/intellij/ide/structureView/StructureView.java +++ b/platform/platform-api/src/com/intellij/ide/structureView/StructureView.java @@ -17,6 +17,7 @@ package com.intellij.ide.structureView; import com.intellij.openapi.Disposable; import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.util.ActionCallback; import javax.swing.*; 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 aa2d7465ce49..bc1e7a6378a5 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 @@ -1562,7 +1562,8 @@ public class AbstractTreeUi { } if (myInitialized.isDone()) { - for (ActionCallback each : getReadyCallbacks(true)) { + ActionCallback[] ready = getReadyCallbacks(true); + for (ActionCallback each : ready) { each.setDone(); } } diff --git a/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java b/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java index 674f0df320bf..adc6e75c7180 100644 --- a/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java +++ b/platform/platform-api/src/com/intellij/util/ui/update/MergingUpdateQueue.java @@ -117,6 +117,9 @@ public class MergingUpdateQueue implements Runnable, Disposable, Activatable { public void cancelAllUpdates() { synchronized (myScheduledUpdates) { + for (Update each : myScheduledUpdates.keySet()) { + each.setRejected(); + } myScheduledUpdates.clear(); } } @@ -317,6 +320,7 @@ public class MergingUpdateQueue implements Runnable, Disposable, Activatable { } if (update.canEat(eachInQueue)) { myScheduledUpdates.remove(eachInQueue); + eachInQueue.setRejected(); } } return false; diff --git a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java index c1fe629ef4d5..94ccf53e6414 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java +++ b/xml/dom-impl/src/com/intellij/util/xml/structure/DomStructureViewBuilder.java @@ -20,8 +20,10 @@ import com.intellij.ide.structureView.StructureView; import com.intellij.ide.structureView.StructureViewModel; import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; import com.intellij.ide.structureView.newStructureView.StructureViewComponent; +import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.AsyncResult; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlTag; @@ -32,8 +34,6 @@ import com.intellij.util.xml.DomManager; import com.intellij.util.xml.DomService; import org.jetbrains.annotations.NotNull; -import javax.swing.tree.DefaultMutableTreeNode; - public class DomStructureViewBuilder extends TreeBasedStructureViewBuilder { private final Function myDescriptor; private final XmlFile myFile; @@ -55,7 +55,7 @@ public class DomStructureViewBuilder extends TreeBasedStructureViewBuilder { @NotNull public StructureView createStructureView(final FileEditor fileEditor, final Project project) { return new StructureViewComponent(fileEditor, createStructureViewModel(), project) { - public DefaultMutableTreeNode expandPathToElement(final Object element) { + public AsyncResult expandPathToElement(final Object element) { if (element instanceof XmlElement) { final XmlElement xmlElement = (XmlElement)element; XmlTag tag = PsiTreeUtil.getParentOfType(xmlElement, XmlTag.class, false); From 73aefce3b8ac760cf2e795260f70cc0ccce83b0a Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Wed, 3 Mar 2010 18:43:52 +0300 Subject: [PATCH 2/2] protocol relative urls (//) fix --- .../com/intellij/openapi/paths/GlobalPathReferenceProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/GlobalPathReferenceProvider.java b/platform/lang-impl/src/com/intellij/openapi/paths/GlobalPathReferenceProvider.java index e71aba5ed132..ae38d5dc0a5f 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/GlobalPathReferenceProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/GlobalPathReferenceProvider.java @@ -39,7 +39,7 @@ public class GlobalPathReferenceProvider implements PathReferenceProvider { } final TextRange range = manipulator.getRangeInElement(psiElement); final String s = range.substring(psiElement.getText()); - if (s.contains("://") || s.startsWith(MAILTO_PREFIX)) { + if (s.contains("://") || s.startsWith(MAILTO_PREFIX) || s.startsWith("//")) { final PsiReference reference = PsiReferenceBase.createSelfReference(psiElement, psiElement); references.add(reference); return true;