2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.codeInsight.daemon.impl;
19 import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask;
20 import com.intellij.find.FindUtil;
21 import com.intellij.ide.PsiCopyPasteManager;
22 import com.intellij.ide.util.PsiElementListCellRenderer;
23 import com.intellij.ide.util.gotoByName.ChooseByNameBase;
24 import com.intellij.openapi.diagnostic.Logger;
25 import com.intellij.openapi.editor.Editor;
26 import com.intellij.openapi.progress.ProgressManager;
27 import com.intellij.openapi.ui.popup.JBPopup;
28 import com.intellij.openapi.ui.popup.PopupChooserBuilder;
29 import com.intellij.openapi.util.Computable;
30 import com.intellij.openapi.util.Ref;
31 import com.intellij.psi.NavigatablePsiElement;
32 import com.intellij.psi.PsiElement;
33 import com.intellij.ui.CollectionListModel;
34 import com.intellij.ui.JBListWithHintProvider;
35 import com.intellij.ui.awt.RelativePoint;
36 import com.intellij.ui.popup.AbstractPopup;
37 import com.intellij.ui.popup.HintUpdateSupply;
38 import com.intellij.usages.UsageView;
39 import com.intellij.util.Consumer;
40 import com.intellij.util.Processor;
41 import org.jetbrains.annotations.NotNull;
42 import org.jetbrains.annotations.Nullable;
45 import java.awt.datatransfer.Transferable;
46 import java.awt.event.MouseEvent;
47 import java.util.List;
49 public class PsiElementListNavigator {
50 private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PsiElementListNavigator");
52 private PsiElementListNavigator() {
55 public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer) {
56 openTargets(e, targets, title, findUsagesTitle, listRenderer, null);
59 public static void openTargets(MouseEvent e,
60 NavigatablePsiElement[] targets,
62 final String findUsagesTitle,
63 ListCellRenderer listRenderer,
64 @Nullable ListBackgroundUpdaterTask listUpdaterTask) {
65 JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, listUpdaterTask);
66 if (popup != null) popup.show(new RelativePoint(e));
69 public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer) {
70 JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, null);
71 if (popup != null) popup.showInBestPositionFor(e);
75 private static JBPopup navigateOrCreatePopup(final NavigatablePsiElement[] targets,
77 final String findUsagesTitle,
78 final ListCellRenderer listRenderer,
79 @Nullable final ListBackgroundUpdaterTask listUpdaterTask) {
80 return navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, listUpdaterTask, new Consumer<Object[]>() {
82 public void consume(Object[] selectedElements) {
83 for (Object element : selectedElements) {
84 PsiElement selected = (PsiElement)element;
85 LOG.assertTrue(selected.isValid());
86 ((NavigatablePsiElement)selected).navigate(true);
93 public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets,
95 final String findUsagesTitle,
96 final ListCellRenderer listRenderer,
97 @Nullable final ListBackgroundUpdaterTask listUpdaterTask,
98 @NotNull final Consumer<Object[]> consumer) {
99 if (targets.length == 0) return null;
100 if (targets.length == 1) {
101 consumer.consume(targets);
104 final CollectionListModel<NavigatablePsiElement> model = new CollectionListModel<NavigatablePsiElement>(targets);
105 final JBListWithHintProvider list = new JBListWithHintProvider(model) {
107 protected PsiElement getPsiElementForHint(final Object selectedValue) {
108 return (PsiElement) selectedValue;
112 list.setTransferHandler(new TransferHandler(){
115 protected Transferable createTransferable(JComponent c) {
116 final Object[] selectedValues = list.getSelectedValues();
117 final PsiElement[] copy = new PsiElement[selectedValues.length];
118 for (int i = 0; i < selectedValues.length; i++) {
119 copy[i] = (PsiElement)selectedValues[i];
121 return new PsiCopyPasteManager.MyTransferable(copy);
125 public int getSourceActions(JComponent c) {
130 list.setCellRenderer(listRenderer);
131 list.setFont(ChooseByNameBase.getEditorFont());
133 final PopupChooserBuilder builder = new PopupChooserBuilder(list);
134 if (listRenderer instanceof PsiElementListCellRenderer) {
135 ((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder);
138 PopupChooserBuilder popupChooserBuilder = builder.
142 setItemChoosenCallback(new Runnable() {
145 int[] ids = list.getSelectedIndices();
146 if (ids == null || ids.length == 0) return;
147 Object[] selectedElements = list.getSelectedValues();
148 consumer.consume(selectedElements);
151 setCancelCallback(new Computable<Boolean>() {
153 public Boolean compute() {
154 HintUpdateSupply.hideHint(list);
158 final Ref<UsageView> usageView = new Ref<UsageView>();
159 if (findUsagesTitle != null) {
160 popupChooserBuilder = popupChooserBuilder.setCouldPin(new Processor<JBPopup>() {
162 public boolean process(JBPopup popup) {
163 final List<NavigatablePsiElement> items = model.getItems();
164 usageView.set(FindUtil.showInUsageView(null, items.toArray(new PsiElement[items.size()]), findUsagesTitle, targets[0].getProject()));
171 final JBPopup popup = popupChooserBuilder.createPopup();
173 builder.getScrollPane().setBorder(null);
174 builder.getScrollPane().setViewportBorder(null);
176 if (listUpdaterTask != null) {
177 listUpdaterTask.init((AbstractPopup)popup, list, usageView);
179 ProgressManager.getInstance().run(listUpdaterTask);