| /* |
| * Copyright 2000-2009 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.ide.hierarchy; |
| |
| import com.intellij.ide.DefaultTreeExpander; |
| import com.intellij.ide.actions.CloseTabToolbarAction; |
| import com.intellij.ide.actions.ContextHelpAction; |
| import com.intellij.ide.util.treeView.AbstractTreeUi; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.actionSystem.*; |
| import com.intellij.openapi.progress.ProgressIndicator; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.ui.SimpleToolWindowPanel; |
| import com.intellij.pom.Navigatable; |
| import com.intellij.psi.NavigatablePsiElement; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.util.PsiUtilCore; |
| import com.intellij.ui.AutoScrollToSourceHandler; |
| import com.intellij.ui.TreeSpeedSearch; |
| import com.intellij.ui.content.Content; |
| import com.intellij.ui.content.tabs.PinToolwindowTabAction; |
| import com.intellij.ui.treeStructure.Tree; |
| import com.intellij.util.ui.UIUtil; |
| import com.intellij.util.ui.tree.TreeUtil; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import javax.swing.tree.DefaultMutableTreeNode; |
| import javax.swing.tree.TreePath; |
| import javax.swing.tree.TreeSelectionModel; |
| import java.util.ArrayList; |
| |
| /** |
| * @author yole |
| */ |
| public abstract class HierarchyBrowserBase extends SimpleToolWindowPanel implements HierarchyBrowser, Disposable, DataProvider { |
| private static final HierarchyNodeDescriptor[] EMPTY_DESCRIPTORS = new HierarchyNodeDescriptor[0]; |
| |
| protected Content myContent; |
| private final AutoScrollToSourceHandler myAutoScrollToSourceHandler; |
| protected final Project myProject; |
| |
| protected HierarchyBrowserBase(@NotNull Project project) { |
| super(true, true); |
| myProject = project; |
| myAutoScrollToSourceHandler = new AutoScrollToSourceHandler() { |
| @Override |
| protected boolean isAutoScrollMode() { |
| return HierarchyBrowserManager.getInstance(myProject).getState().IS_AUTOSCROLL_TO_SOURCE; |
| } |
| |
| @Override |
| protected void setAutoScrollMode(final boolean state) { |
| HierarchyBrowserManager.getInstance(myProject).getState().IS_AUTOSCROLL_TO_SOURCE = state; |
| } |
| }; |
| } |
| |
| @Override |
| public void setContent(final Content content) { |
| myContent = content; |
| } |
| |
| protected void buildUi(JComponent toolbar, JComponent content) { |
| setToolbar(toolbar); |
| setContent(content); |
| } |
| |
| @Override |
| public void dispose() { |
| } |
| |
| protected ActionToolbar createToolbar(final String place, final String helpID) { |
| final DefaultActionGroup actionGroup = new DefaultActionGroup(); |
| appendActions(actionGroup, helpID); |
| final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(place, actionGroup, true); |
| actionToolbar.setTargetComponent(this); |
| return actionToolbar; |
| } |
| |
| protected void appendActions(@NotNull DefaultActionGroup actionGroup, @Nullable String helpID) { |
| actionGroup.add(myAutoScrollToSourceHandler.createToggleAction()); |
| actionGroup.add(ActionManager.getInstance().getAction(IdeActions.ACTION_EXPAND_ALL)); |
| actionGroup.add(new PinToolwindowTabAction(){ |
| @Override |
| public void update(AnActionEvent event) { |
| super.update(event); |
| // sometimes there is no content to close, e.g. in usage view preview |
| event.getPresentation().setVisible(myContent != null); |
| } |
| }); |
| actionGroup.add(new CloseAction()); |
| if (helpID != null) { |
| actionGroup.add(new ContextHelpAction(helpID)); |
| } |
| } |
| |
| protected abstract JTree getCurrentTree(); |
| protected abstract HierarchyTreeBuilder getCurrentBuilder(); |
| |
| @Nullable |
| protected abstract PsiElement getElementFromDescriptor(@NotNull HierarchyNodeDescriptor descriptor); |
| |
| @Nullable |
| protected DefaultMutableTreeNode getSelectedNode() { |
| final JTree tree = getCurrentTree(); |
| if (tree == null) return null; |
| final TreePath path = tree.getSelectionPath(); |
| if (path == null) return null; |
| final Object lastPathComponent = path.getLastPathComponent(); |
| if (!(lastPathComponent instanceof DefaultMutableTreeNode)) return null; |
| return (DefaultMutableTreeNode)lastPathComponent; |
| } |
| |
| @Nullable |
| protected final PsiElement getSelectedElement() { |
| final DefaultMutableTreeNode node = getSelectedNode(); |
| final HierarchyNodeDescriptor descriptor = node != null ? getDescriptor(node) : null; |
| return descriptor != null ? getElementFromDescriptor(descriptor) : null; |
| } |
| |
| @Nullable |
| protected HierarchyNodeDescriptor getDescriptor(DefaultMutableTreeNode node) { |
| final Object userObject = node != null ? node.getUserObject() : null; |
| if (userObject instanceof HierarchyNodeDescriptor) { |
| return (HierarchyNodeDescriptor)userObject; |
| } |
| return null; |
| } |
| |
| public final HierarchyNodeDescriptor[] getSelectedDescriptors() { |
| final JTree tree = getCurrentTree(); |
| if (tree == null) { |
| return EMPTY_DESCRIPTORS; |
| } |
| final TreePath[] paths = tree.getSelectionPaths(); |
| if (paths == null || paths.length == 0) { |
| return EMPTY_DESCRIPTORS; |
| } |
| final ArrayList<HierarchyNodeDescriptor> list = new ArrayList<HierarchyNodeDescriptor>(paths.length); |
| for (final TreePath path : paths) { |
| final Object lastPathComponent = path.getLastPathComponent(); |
| if (lastPathComponent instanceof DefaultMutableTreeNode) { |
| final DefaultMutableTreeNode node = (DefaultMutableTreeNode)lastPathComponent; |
| HierarchyNodeDescriptor descriptor = getDescriptor(node); |
| if (descriptor != null) { |
| list.add(descriptor); |
| } |
| } |
| } |
| return list.toArray(new HierarchyNodeDescriptor[list.size()]); |
| } |
| |
| @NotNull |
| protected PsiElement[] getSelectedElements() { |
| HierarchyNodeDescriptor[] descriptors = getSelectedDescriptors(); |
| ArrayList<PsiElement> elements = new ArrayList<PsiElement>(); |
| for (HierarchyNodeDescriptor descriptor : descriptors) { |
| PsiElement element = getElementFromDescriptor(descriptor); |
| if (element != null) elements.add(element); |
| } |
| return PsiUtilCore.toPsiElementArray(elements); |
| } |
| |
| |
| private Navigatable[] getNavigatables() { |
| final HierarchyNodeDescriptor[] selectedDescriptors = getSelectedDescriptors(); |
| if (selectedDescriptors == null || selectedDescriptors.length == 0) return null; |
| final ArrayList<Navigatable> result = new ArrayList<Navigatable>(); |
| for (HierarchyNodeDescriptor descriptor : selectedDescriptors) { |
| Navigatable navigatable = getNavigatable(descriptor); |
| if (navigatable != null) { |
| result.add(navigatable); |
| } |
| } |
| return result.toArray(new Navigatable[result.size()]); |
| } |
| |
| private Navigatable getNavigatable(HierarchyNodeDescriptor descriptor) { |
| if (descriptor instanceof Navigatable && descriptor.isValid()) { |
| return (Navigatable)descriptor; |
| } |
| |
| PsiElement element = getElementFromDescriptor(descriptor); |
| if (element instanceof NavigatablePsiElement && element.isValid()) { |
| return (NavigatablePsiElement)element; |
| } |
| return null; |
| } |
| |
| @Override |
| @Nullable |
| public Object getData(@NonNls final String dataId) { |
| if (CommonDataKeys.PSI_ELEMENT.is(dataId)) { |
| final PsiElement anElement = getSelectedElement(); |
| return anElement != null && anElement.isValid() ? anElement : super.getData(dataId); |
| } |
| if (LangDataKeys.PSI_ELEMENT_ARRAY.is(dataId)) { |
| return getSelectedElements(); |
| } |
| if (PlatformDataKeys.DELETE_ELEMENT_PROVIDER.is(dataId)) { |
| return null; |
| } |
| if (CommonDataKeys.NAVIGATABLE.is(dataId)) { |
| final DefaultMutableTreeNode selectedNode = getSelectedNode(); |
| if (selectedNode == null) return null; |
| final HierarchyNodeDescriptor descriptor = getDescriptor(selectedNode); |
| if (descriptor == null) return null; |
| return getNavigatable(descriptor); |
| } |
| if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) { |
| return getNavigatables(); |
| } |
| if (PlatformDataKeys.TREE_EXPANDER.is(dataId)) { |
| final JTree tree = getCurrentTree(); |
| if (tree != null) { |
| return new DefaultTreeExpander(tree); |
| } |
| } |
| return super.getData(dataId); |
| } |
| |
| private final class CloseAction extends CloseTabToolbarAction { |
| private CloseAction() { |
| } |
| |
| @Override |
| public final void actionPerformed(final AnActionEvent e) { |
| final HierarchyTreeBuilder builder = getCurrentBuilder(); |
| final AbstractTreeUi treeUi = builder != null ? builder.getUi() : null; |
| final ProgressIndicator progress = treeUi != null ? treeUi.getProgress() : null; |
| if (progress != null) { |
| progress.cancel(); |
| } |
| myContent.getManager().removeContent(myContent, true); |
| } |
| |
| @Override |
| public void update(AnActionEvent e) { |
| e.getPresentation().setVisible(myContent != null); |
| } |
| } |
| |
| protected void configureTree(@NotNull Tree tree) { |
| tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); |
| tree.setToggleClickCount(-1); |
| tree.setCellRenderer(new HierarchyNodeRenderer()); |
| UIUtil.setLineStyleAngled(tree); |
| new TreeSpeedSearch(tree); |
| TreeUtil.installActions(tree); |
| myAutoScrollToSourceHandler.install(tree); |
| } |
| |
| } |