diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 256452a8a04a..bcecd4a55f6e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -45,6 +45,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.ui.*; import com.intellij.ui.popup.AbstractPopup; +import com.intellij.ui.popup.PopupUpdateProcessor; import com.intellij.ui.speedSearch.ElementFilter; import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.ui.treeStructure.Tree; @@ -64,6 +65,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import java.awt.*; @@ -143,10 +146,18 @@ public class FileStructurePopup implements Disposable { return "structure view tree structure(model=" + myTreeModel + ")"; } }; - myTree = new Tree(new DefaultMutableTreeNode(myTreeStructure.getRootElement())); - myTree.setCellRenderer(new NodeRenderer(){ + myTree = new JBTreeWithHintProvider(new DefaultMutableTreeNode(myTreeStructure.getRootElement())) { @Override - protected void doAppend(@NotNull @Nls String fragment, @NotNull SimpleTextAttributes attributes, boolean isMainText, boolean selected) { + protected PsiElement getPsiElementForHint(Object selectedValue) { + return getPsi((FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)selectedValue).getUserObject()); + } + }; + myTree.setCellRenderer(new NodeRenderer() { + @Override + protected void doAppend(@NotNull @Nls String fragment, + @NotNull SimpleTextAttributes attributes, + boolean isMainText, + boolean selected) { SpeedSearchUtil.appendFragmentsForSpeedSearch(myTree, fragment, attributes, selected, this); } @@ -310,7 +321,7 @@ public class FileStructurePopup implements Disposable { .setModalContext(false) .setFocusable(true) .setMovable(true) - .setBelongsToGlobalPopupStack(true) + .setBelongsToGlobalPopupStack(true) //.setCancelOnClickOutside(false) //for debug and snapshots .setCancelKeyEnabled(false) .setDimensionServiceKey(null, getDimensionServiceKey(), false) @@ -322,6 +333,19 @@ public class FileStructurePopup implements Disposable { } }) .createPopup(); + + myTree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + if (myPopup.isVisible()) { + final PopupUpdateProcessor updateProcessor = myPopup.getUserData(PopupUpdateProcessor.class); + if (updateProcessor != null) { + final AbstractTreeNode node = getSelectedNode(); + updateProcessor.updatePopup(node); + } + } + } + }); Disposer.register(myPopup, this); Disposer.register(myPopup, new Disposable() { @Override @@ -342,6 +366,7 @@ public class FileStructurePopup implements Disposable { if (shouldSetWidth) { myPopup.setSize(new Dimension(myPreferredWidth + 10, myPopup.getSize().height)); } + myAbstractTreeBuilder.expandAll(new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java b/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java new file mode 100644 index 000000000000..b2ba5b742010 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ui/JBTreeWithHintProvider.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ui; + +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.psi.PsiElement; +import com.intellij.ui.popup.PopupUpdateProcessor; +import com.intellij.ui.treeStructure.Tree; + +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +/** + * @author Konstantin Bulenkov + */ +public abstract class JBTreeWithHintProvider extends Tree { + private JBPopup myHint; + + public JBTreeWithHintProvider() { + addSelectionListener(); + } + + public JBTreeWithHintProvider(TreeModel treemodel) { + super(treemodel); + addSelectionListener(); + } + + public JBTreeWithHintProvider(TreeNode root) { + super(root); + addSelectionListener(); + } + + private void addSelectionListener() { + addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(final TreeSelectionEvent e) { + if (getClientProperty(PopupChooserBuilder.SELECTED_BY_MOUSE_EVENT) != Boolean.TRUE) { + final TreePath path = getSelectionPath(); + if (path != null) { + final PsiElement psiElement = getPsiElementForHint(path.getLastPathComponent()); + if (psiElement != null && psiElement.isValid()) { + updateHint(psiElement); + } + } + } + } + }); + } + + protected abstract PsiElement getPsiElementForHint(final Object selectedValue); + + public void registerHint(final JBPopup hint) { + hideHint(); + myHint = hint; + } + + public void hideHint() { + if (myHint != null && myHint.isVisible()) { + myHint.cancel(); + } + + myHint = null; + } + + public void updateHint(PsiElement element) { + if (myHint == null || !myHint.isVisible()) return; + + final PopupUpdateProcessor updateProcessor = myHint.getUserData(PopupUpdateProcessor.class); + if (updateProcessor != null) { + updateProcessor.updatePopup(element); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java b/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java index 2d0dcde1b5fc..cedb27689301 100644 --- a/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java +++ b/platform/lang-impl/src/com/intellij/ui/popup/PopupUpdateProcessor.java @@ -27,6 +27,7 @@ import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.psi.PsiElement; import com.intellij.ui.JBListWithHintProvider; import com.intellij.ui.JBTableWithHintProvider; +import com.intellij.ui.JBTreeWithHintProvider; import java.awt.*; @@ -76,6 +77,8 @@ public abstract class PopupUpdateProcessor extends JBPopupAdapter { ((JBListWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); } else if (focusedComponent instanceof JBTableWithHintProvider) { ((JBTableWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); + } else if (focusedComponent instanceof JBTreeWithHintProvider) { + ((JBTreeWithHintProvider)focusedComponent).registerHint(windowEvent.asPopup()); } } }