dock lists with results in usages toolwindow (IDEA-94094)

This commit is contained in:
anna
2012-12-04 19:22:27 +01:00
parent 7945f8a7de
commit e98da1e89f
15 changed files with 126 additions and 63 deletions
@@ -96,6 +96,7 @@ public class MarkerType {
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(superMethods);
PsiElementListNavigator.openTargets(e, superMethods,
DaemonBundle.message("navigation.title.super.method", method.getName()),
DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()),
new MethodCellRenderer(showMethodNames));
}
@@ -164,7 +165,7 @@ public class MarkerType {
MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames);
Arrays.sort(overridings, renderer.getComparator());
final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer);
PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater);
PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), "Overriding methods of " + method.getName(), renderer, methodsUpdater);
}
public static final String SEARCHING_FOR_OVERRIDDEN_METHODS = "Searching for overridden methods";
@@ -231,7 +232,7 @@ public class MarkerType {
final PsiClassListCellRenderer renderer = new PsiClassListCellRenderer();
final SubclassUpdater subclassUpdater = new SubclassUpdater(aClass, renderer);
Arrays.sort(inheritors, renderer.getComparator());
PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), renderer, subclassUpdater);
PsiElementListNavigator.openTargets(e, inheritors, subclassUpdater.getCaption(inheritors.length), CodeInsightBundle.message("goto.implementation.findUsages.title", aClass.getName()), renderer, subclassUpdater);
}
private final GutterIconNavigationHandler<PsiElement> handler;
@@ -54,6 +54,7 @@ public class JavaGotoSuperHandler implements CodeInsightActionHandler {
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature((PsiMethod[])superElements);
PsiElementListNavigator.openTargets(editor, (PsiMethod[])superElements,
CodeInsightBundle.message("goto.super.method.chooser.title"),
CodeInsightBundle.message("goto.super.method.findUsages.title", ((PsiMethod)superElements[0]).getName()),
new MethodCellRenderer(showMethodNames));
}
else {
@@ -29,7 +29,7 @@ public class DefaultGutterIconNavigationHandler<T extends PsiElement> implements
public void navigate(MouseEvent e, T elt) {
PsiElementListNavigator.openTargets(e,
myReferences.toArray(new NavigatablePsiElement[myReferences.size()]),
myTitle, createListCellRenderer());
myTitle, null, createListCellRenderer());
}
protected ListCellRenderer createListCellRenderer() {
@@ -17,6 +17,7 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask;
import com.intellij.find.FindUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -30,10 +31,12 @@ import com.intellij.ui.CollectionListModel;
import com.intellij.ui.JBListWithHintProvider;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.util.List;
public class PsiElementListNavigator {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PsiElementListNavigator");
@@ -41,27 +44,29 @@ public class PsiElementListNavigator {
private PsiElementListNavigator() {
}
public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) {
openTargets(e, targets, title, listRenderer, null);
public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer) {
openTargets(e, targets, title, findUsagesTitle, listRenderer, null);
}
public static void openTargets(MouseEvent e,
NavigatablePsiElement[] targets,
String title,
final String findUsagesTitle,
ListCellRenderer listRenderer,
@Nullable ListBackgroundUpdaterTask listUpdaterTask) {
JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer, listUpdaterTask);
JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, listUpdaterTask);
if (popup != null) popup.show(new RelativePoint(e));
}
public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, ListCellRenderer listRenderer) {
JBPopup popup = navigateOrCreatePopup(targets, title, listRenderer, null);
public static void openTargets(Editor e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer) {
JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, null);
if (popup != null) popup.showInBestPositionFor(e);
}
@Nullable
private static JBPopup navigateOrCreatePopup(final NavigatablePsiElement[] targets,
final String title,
final String findUsagesTitle,
final ListCellRenderer listRenderer,
final @Nullable ListBackgroundUpdaterTask listUpdaterTask) {
if (targets.length == 0) return null;
@@ -69,7 +74,8 @@ public class PsiElementListNavigator {
targets[0].navigate(true);
return null;
}
final JBListWithHintProvider list = new JBListWithHintProvider(new CollectionListModel(targets)) {
final CollectionListModel<NavigatablePsiElement> model = new CollectionListModel<NavigatablePsiElement>(targets);
final JBListWithHintProvider list = new JBListWithHintProvider(model) {
@Override
protected PsiElement getPsiElementForHint(final Object selectedValue) {
return (PsiElement) selectedValue;
@@ -83,7 +89,7 @@ public class PsiElementListNavigator {
((PsiElementListCellRenderer)listRenderer).installSpeedSearch(builder);
}
final JBPopup popup = builder.
PopupChooserBuilder popupChooserBuilder = builder.
setTitle(title).
setMovable(true).
setItemChoosenCallback(new Runnable() {
@@ -106,9 +112,20 @@ public class PsiElementListNavigator {
return true;
}
})
.createPopup();
});
if (findUsagesTitle != null) {
popupChooserBuilder = popupChooserBuilder.setCouldPin(new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
final List<NavigatablePsiElement> items = model.getItems();
FindUtil.showInUsageView(null, items.toArray(new PsiElement[items.size()]), findUsagesTitle, targets[0].getProject());
popup.cancel();
return false;
}
});
}
final JBPopup popup = popupChooserBuilder.createPopup();
if (listUpdaterTask != null) {
listUpdaterTask.init((AbstractPopup)popup, list);
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.hint;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.find.FindUtil;
import com.intellij.icons.AllIcons;
import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.navigation.ItemPresentation;
@@ -32,7 +33,6 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.popup.JBPopup;
@@ -45,11 +45,6 @@ import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.SideBorder;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.UsageInfoToUsageConverter;
import com.intellij.usages.UsageTarget;
import com.intellij.usages.UsageViewManager;
import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -482,10 +477,6 @@ public class ImplementationViewComponent extends JPanel {
edit.registerCustomShortcutSet(new CompositeShortcutSet(CommonShortcuts.getViewSource(), CommonShortcuts.CTRL_ENTER), this);
group.add(edit);
final ShowFindUsagesAction findUsagesAction = new ShowFindUsagesAction();
findUsagesAction.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts(IdeActions.ACTION_FIND_USAGES)), this);
group.add(findUsagesAction);
return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true);
}
@@ -507,6 +498,13 @@ public class ImplementationViewComponent extends JPanel {
return myElements;
}
public void showInUsageView() {
FindUtil.showInUsageView(null, collectNonBinaryElements(), myTitle, myEditor.getProject());
if (myHint.isVisible()) {
myHint.cancel();
}
}
private class BackAction extends AnAction implements HintManagerImpl.ActionToIgnore {
public BackAction() {
super(CodeInsightBundle.message("quick.definition.back"), null, AllIcons.Actions.Back);
@@ -589,38 +587,6 @@ public class ImplementationViewComponent extends JPanel {
}
}
private class ShowFindUsagesAction extends AnAction {
private static final String ACTION_NAME = "Show in usage view";
public ShowFindUsagesAction() {
super(ACTION_NAME, ACTION_NAME, AllIcons.Actions.Find);
}
@Override
public void actionPerformed(final AnActionEvent e) {
final UsageViewPresentation presentation = new UsageViewPresentation();
presentation.setCodeUsagesString(myTitle);
presentation.setTabName(myTitle);
presentation.setTabText(myTitle);
PsiElement[] elements = collectNonBinaryElements();
final UsageInfo[] usages = new UsageInfo[elements.length];
for (int i = 0; i < elements.length; i++) {
usages[i] = new UsageInfo(elements[i]);
}
UsageViewManager.getInstance(myEditor.getProject()).showUsages(UsageTarget.EMPTY_ARRAY, UsageInfoToUsageConverter.convert(
new UsageInfoToUsageConverter.TargetElementsDescriptor(elements), usages), presentation);
if (myHint.isVisible()) {
myHint.cancel();
}
}
@Override
public void update(AnActionEvent e) {
if (myElements == null) return;
e.getPresentation().setVisible(collectNonBinaryElements().length > 0);
}
}
private PsiElement[] collectNonBinaryElements() {
List<PsiElement> result = new ArrayList<PsiElement>();
for (PsiElement element : myElements) {
@@ -46,6 +46,7 @@ import com.intellij.ui.popup.AbstractPopup;
import com.intellij.ui.popup.NotLookupOrSearchCondition;
import com.intellij.ui.popup.PopupPositionManager;
import com.intellij.ui.popup.PopupUpdateProcessor;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -238,6 +239,13 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
.setMovable(true)
.setRequestFocus(invokedFromEditor && LookupManager.getActiveLookup(editor) == null)
.setTitle(title)
.setCouldPin(new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
component.showInUsageView();
return false;
}
})
.createPopup();
updateInBackground(editor, element, component, title, (AbstractPopup)popup);
@@ -83,6 +83,11 @@ public class GotoImplementationHandler extends GotoTargetHandler {
return CodeInsightBundle.message("goto.implementation.chooserTitle", name, length);
}
@Override
protected String getFindUsagesTitle(PsiElement sourceElement, String name, int length) {
return CodeInsightBundle.message("goto.implementation.findUsages.title", name, length);
}
@Override
protected String getNotFoundMessage(Project project, Editor editor, PsiFile file) {
return CodeInsightBundle.message("goto.implementation.notFound");
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.navigation;
import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.find.FindUtil;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
import com.intellij.navigation.ItemPresentation;
@@ -42,6 +43,7 @@ import com.intellij.ui.JBListWithHintProvider;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -82,9 +84,9 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
@Nullable
protected abstract GotoData getSourceAndTargetElements(Editor editor, PsiFile file);
private void show(Project project,
private void show(final Project project,
Editor editor,
PsiFile file,
final PsiFile file,
final GotoData gotoData) {
final PsiElement[] targets = gotoData.targets;
final List<AdditionalAction> additionalActions = gotoData.additionalActions;
@@ -106,8 +108,8 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
gotoData.renderers.put(eachTarget, createRenderer(gotoData, eachTarget));
}
String name = ((PsiNamedElement)gotoData.source).getName();
String title = getChooserTitle(gotoData.source, name, targets.length);
final String name = ((PsiNamedElement)gotoData.source).getName();
final String title = getChooserTitle(gotoData.source, name, targets.length);
if (shouldSortTargets()) {
Arrays.sort(targets, createComparator(gotoData.renderers, gotoData));
@@ -178,6 +180,15 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
return true;
}
}).
setCouldPin(new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
FindUtil.showInUsageView(gotoData.source, gotoData.targets,
getFindUsagesTitle(gotoData.source, name, gotoData.targets.length), project);
popup.cancel();
return false;
}
}).
setAdText(getAdText(gotoData.source, targets.length)).
createPopup();
if (gotoData.listUpdaterTask != null) {
@@ -238,6 +249,9 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
}
protected abstract String getChooserTitle(PsiElement sourceElement, String name, int length);
protected String getFindUsagesTitle(PsiElement sourceElement, String name, int length) {
return getChooserTitle(sourceElement, name, length);
}
protected abstract String getNotFoundMessage(Project project, Editor editor, PsiFile file);
@Nullable
@@ -19,6 +19,7 @@ package com.intellij.find;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.find.impl.FindInProjectUtil;
import com.intellij.find.replaceInProject.ReplaceInProjectManager;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -54,6 +55,7 @@ import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.ui.LightweightHint;
import com.intellij.usageView.UsageInfo;
@@ -907,4 +909,20 @@ public class FindUtil {
public interface ReplaceDelegate {
boolean shouldReplace(TextRange range, String replace);
}
public static void showInUsageView(PsiElement sourceElement, PsiElement[] targets, String title, Project project) {
final UsageViewPresentation presentation = new UsageViewPresentation();
presentation.setCodeUsagesString(title);
presentation.setTabName(title);
presentation.setTabText(title);
final UsageInfo[] usages = new UsageInfo[targets.length];
for (int i = 0; i < targets.length; i++) {
usages[i] = new UsageInfo(targets[i]);
}
final UsageTarget[] usageTargets =
sourceElement == null ? UsageTarget.EMPTY_ARRAY : new UsageTarget[]{new PsiElement2UsageTargetAdapter(sourceElement)};
final Usage[] foundUsages = UsageInfoToUsageConverter.convert(
new UsageInfoToUsageConverter.TargetElementsDescriptor(targets), usages);
UsageViewManager.getInstance(project).showUsages(usageTargets, foundUsages, presentation);
}
}
@@ -30,7 +30,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
@@ -102,6 +101,16 @@ public class GotoTestOrCodeHandler extends GotoTargetHandler {
}
}
@Override
protected String getFindUsagesTitle(PsiElement sourceElement, String name, int length) {
if (TestFinderHelper.isTest(sourceElement)) {
return CodeInsightBundle.message("goto.test.findUsages.subject.title", name);
}
else {
return CodeInsightBundle.message("goto.test.findUsages.test.title", name);
}
}
@Override
protected String getNotFoundMessage(Project project, Editor editor, PsiFile file) {
return CodeInsightBundle.message("goto.test.notFound");
@@ -30,6 +30,7 @@ import com.intellij.ui.components.JBViewport;
import com.intellij.ui.speedSearch.ListWithFilter;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.Nls;
@@ -84,6 +85,7 @@ public class PopupChooserBuilder {
private boolean myCloseOnEnter = true;
private boolean myCancelOnWindowDeactivation = true;
private boolean myUseForXYLocation;
@Nullable private Processor<JBPopup> myCouldPin;
public PopupChooserBuilder setCancelOnClickOutside(boolean cancelOnClickOutside) {
myCancelOnClickOutside = cancelOnClickOutside;
@@ -138,6 +140,12 @@ public class PopupChooserBuilder {
return this;
}
@NotNull
public PopupChooserBuilder setCouldPin(@Nullable Processor<JBPopup> callback){
myCouldPin = callback;
return this;
}
@NotNull
public PopupChooserBuilder setEastComponent(@NotNull JComponent cmp) {
myEastComponent = cmp;
@@ -307,7 +315,8 @@ public class PopupChooserBuilder {
.setCancelOnOtherWindowOpen(true)
.setModalContext(myModalContext)
.setCancelOnWindowDeactivation(myCancelOnWindowDeactivation)
.setCancelOnClickOutside(myCancelOnClickOutside);
.setCancelOnClickOutside(myCancelOnClickOutside)
.setCouldPin(myCouldPin);
if (myCommandButton != null) {
builder.setCommandButton(myCommandButton);
@@ -252,14 +252,18 @@ javadoc.external.fetch.error.message=Cannot fetch remote documentation: {0}
searching.for.implementations=Searching For Implementations...
goto.implementation.chooserTitle=<html><body>Choose Implementation of <b>{0}</b> ({1} found)</body></html>
goto.implementation.findUsages.title=Implementations of {0}
goto.implementation.notFound=No implementations found
goto.test.chooserTitle.test=<html><body>Choose Test for <b>{0}</b> ({1} found)</body></html>
goto.test.findUsages.test.title=Tests for {0}
goto.test.chooserTitle.subject=<html><body>Choose Test Subject for <b>{0}</b> ({1} found)</body></html>
goto.test.findUsages.subject.title=Test Subjects for {0}
goto.test.notFound=No test subjects found
incremental.search.tooltip.prefix=Search for:
goto.super.method.chooser.title=Choose super method
goto.super.method.findUsages.title=Super methods of {0}
goto.super.class.chooser.title=Choose super class or interface
javadoc.action.back=Back
javadoc.action.forward=Forward
@@ -38,6 +38,7 @@ interface.is.implemented.by.header=Is implemented by<br>
class.is.subclassed.by.header=Is subclassed by<br>
navigation.title.super.method=Choose Super Method of {0}
navigation.findUsages.title.super.method=Super Methods of {0}
navigation.title.implementation.method=<html><body>Choose Implementation of <b>{0}</b> ({1} methods found)</body></html>
navigation.title.overrider.method=<html><body>Choose Overriding Method of <b>{0}</b> ({1} methods found)</body></html>
navigation.title.subclass=<html><body>Choose Subclass of <b>{0}</b> ({1} classes found)</body></html>
@@ -108,7 +108,9 @@ public class GroovyMarkerTypes {
if (superMethods.isEmpty()) return;
final PsiMethod[] supers = ContainerUtil.toArray(superMethods, new PsiMethod[superMethods.size()]);
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(supers);
PsiElementListNavigator.openTargets(e, supers, DaemonBundle.message("navigation.title.super.method", field.getName()),
PsiElementListNavigator.openTargets(e, supers,
DaemonBundle.message("navigation.title.super.method", field.getName()),
DaemonBundle.message("navigation.findUsages.title.super.method", field.getName()),
new MethodCellRenderer(showMethodNames));
}
});
@@ -170,7 +172,7 @@ public class GroovyMarkerTypes {
boolean showMethodNames = !PsiUtil.allMethodsHaveSameSignature(overridings);
MethodCellRenderer renderer = new MethodCellRenderer(showMethodNames);
Arrays.sort(overridings, renderer.getComparator());
PsiElementListNavigator.openTargets(e, overridings, title, renderer);
PsiElementListNavigator.openTargets(e, overridings, title, "Overriding Methods of " + field.getName(), renderer);
}
}
);
@@ -209,6 +211,7 @@ public class GroovyMarkerTypes {
if (superMethods.isEmpty()) return;
PsiElementListNavigator.openTargets(e, superMethods.toArray(new NavigatablePsiElement[superMethods.size()]),
DaemonBundle.message("navigation.title.super.method", method.getName()),
DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()),
new MethodCellRenderer(true));
}
@@ -282,7 +285,9 @@ public class GroovyMarkerTypes {
PsiElementListCellRenderer<PsiMethod> renderer = new MethodCellRenderer(!PsiUtil.allMethodsHaveSameSignature(overridings));
Arrays.sort(overridings, renderer.getComparator());
final OverridingMethodsUpdater methodsUpdater = new OverridingMethodsUpdater(method, renderer);
PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length), renderer, methodsUpdater);
PsiElementListNavigator.openTargets(e, overridings, methodsUpdater.getCaption(overridings.length),
"Overriding Methods of " + method.getName(),
renderer, methodsUpdater);
}
});
@@ -60,6 +60,11 @@ public class GroovyGotoSuperHandler extends GotoTargetHandler implements CodeIns
return CodeInsightBundle.message("goto.super.method.chooser.title");
}
@Override
protected String getFindUsagesTitle(PsiElement sourceElement, String name, int length) {
return CodeInsightBundle.message("goto.super.method.findUsages.title", name);
}
@Override
protected String getNotFoundMessage(Project project, Editor editor, PsiFile file) {
final PsiMember source = findSource(editor, file);