search for yet non-loaded elements in list in background

This commit is contained in:
anna
2012-12-06 13:22:28 +01:00
parent 536a46956d
commit f81ebf39b3
7 changed files with 77 additions and 27 deletions
@@ -25,12 +25,14 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
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.usages.UsageView;
import com.intellij.util.Processor;
import org.jetbrains.annotations.Nullable;
@@ -113,12 +115,13 @@ public class PsiElementListNavigator {
return true;
}
});
final Ref<UsageView> usageView = new Ref<UsageView>();
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());
usageView.set(FindUtil.showInUsageView(null, items.toArray(new PsiElement[items.size()]), findUsagesTitle, targets[0].getProject()));
popup.cancel();
return false;
}
@@ -127,7 +130,7 @@ public class PsiElementListNavigator {
final JBPopup popup = popupChooserBuilder.createPopup();
if (listUpdaterTask != null) {
listUpdaterTask.init((AbstractPopup)popup, list);
listUpdaterTask.init((AbstractPopup)popup, list, usageView);
ProgressManager.getInstance().run(listUpdaterTask);
}
@@ -45,6 +45,7 @@ import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.SideBorder;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.usages.UsageView;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -337,7 +338,7 @@ public class ImplementationViewComponent extends JPanel {
if (file == null) continue;
final PsiElement parent = element.getParent();
files.add(new FileDescriptor(file, names.size() > 1 || parent == file ? element : parent));
candidates.add(element.getNavigationElement());
candidates.add(element);
}
fun.fun(PsiUtilCore.toPsiElementArray(candidates), files);
@@ -367,7 +368,7 @@ public class ImplementationViewComponent extends JPanel {
private void updateEditorText() {
disposeNonTextEditor();
final PsiElement elt = myElements[myIndex];
final PsiElement elt = myElements[myIndex].getNavigationElement();
Project project = elt.getProject();
PsiFile psiFile = getContainingFile(elt);
final VirtualFile vFile = psiFile.getVirtualFile();
@@ -498,11 +499,8 @@ public class ImplementationViewComponent extends JPanel {
return myElements;
}
public void showInUsageView() {
FindUtil.showInUsageView(null, collectNonBinaryElements(), myTitle, myEditor.getProject());
if (myHint.isVisible()) {
myHint.cancel();
}
public UsageView showInUsageView() {
return FindUtil.showInUsageView(null, collectNonBinaryElements(), myTitle, myEditor.getProject());
}
private class BackAction extends AnAction implements HintManagerImpl.ActionToIgnore {
@@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.PomTargetPsiElement;
import com.intellij.psi.*;
@@ -46,6 +47,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.usages.UsageView;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -204,6 +206,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
}
}
final Ref<UsageView> usageView = new Ref<UsageView>();
final String title = CodeInsightBundle.message("implementation.view.title", text);
if (myPopupRef != null) {
final JBPopup popup = myPopupRef.get();
@@ -211,7 +214,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
final ImplementationViewComponent component = (ImplementationViewComponent) ((AbstractPopup)popup).getComponent();
((AbstractPopup)popup).setCaption(title);
component.update(impls, index);
updateInBackground(editor, element, component, title, (AbstractPopup)popup);
updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView);
if (invokedByShortcut) {
((AbstractPopup)popup).focusPreferredComponent();
}
@@ -242,13 +245,14 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
.setCouldPin(new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
component.showInUsageView();
usageView.set(component.showInUsageView());
popup.cancel();
return false;
}
})
.createPopup();
updateInBackground(editor, element, component, title, (AbstractPopup)popup);
updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView);
PopupPositionManager.positionPopupInBestPosition(popup, editor, DataManager.getInstance().getDataContext());
component.setHint(popup, title);
@@ -261,7 +265,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
@Nullable PsiElement element,
ImplementationViewComponent component,
String title,
AbstractPopup popup) {
AbstractPopup popup, Ref<UsageView> usageView) {
if (myTaskRef != null) {
final BackgroundUpdaterTask updaterTask = myTaskRef.get();
if (updaterTask != null) {
@@ -271,7 +275,7 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
if (element == null) return; //already found
final ImplementationsUpdaterTask task = new ImplementationsUpdaterTask(element, editor, title);
task.init(popup, component);
task.init(popup, component, usageView);
myTaskRef = new WeakReference<BackgroundUpdaterTask>(task);
ProgressManager.getInstance().run(task);
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.navigation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -22,8 +23,13 @@ import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.UsageInfo2UsageAdapter;
import com.intellij.usages.UsageView;
import com.intellij.usages.impl.UsageViewImpl;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +45,7 @@ import java.util.List;
public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
protected AbstractPopup myPopup;
protected T myComponent;
private Ref<UsageView> myUsageView;
private final List<PsiElement> myData = new ArrayList<PsiElement>();
private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
@@ -61,9 +68,10 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
super(project, title, canBeCancelled, backgroundOption);
}
public void init(@NotNull AbstractPopup popup, T component) {
public void init(@NotNull AbstractPopup popup, T component, Ref<UsageView> usageView) {
myPopup = popup;
myComponent = component;
myUsageView = usageView;
myPopup.addPopupListener(new JBPopupAdapter() {
@Override
@@ -83,7 +91,17 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
return canceled;
}
public boolean updateComponent(PsiElement element, @Nullable final Comparator comparator) {
public boolean updateComponent(final PsiElement element, @Nullable final Comparator comparator) {
final UsageView view = myUsageView.get();
if (view != null && !((UsageViewImpl)view).isDisposed()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
view.appendUsage(new UsageInfo2UsageAdapter(new UsageInfo(element)));
}
});
return true;
}
if (myCanceled) return false;
if (myPopup.isDisposed()) return false;
@@ -34,6 +34,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -41,6 +42,7 @@ import com.intellij.psi.PsiNamedElement;
import com.intellij.ui.CollectionListModel;
import com.intellij.ui.JBListWithHintProvider;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.usages.UsageView;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
@@ -169,6 +171,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
}
});
final Ref<UsageView> usageView = new Ref<UsageView>();
final JBPopup popup = builder.
setTitle(title).
setItemChoosenCallback(runnable).
@@ -183,8 +186,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
setCouldPin(new Processor<JBPopup>() {
@Override
public boolean process(JBPopup popup) {
FindUtil.showInUsageView(gotoData.source, gotoData.targets,
getFindUsagesTitle(gotoData.source, name, gotoData.targets.length), project);
usageView.set(FindUtil.showInUsageView(gotoData.source, gotoData.targets, getFindUsagesTitle(gotoData.source, name, gotoData.targets.length), project));
popup.cancel();
return false;
}
@@ -192,7 +194,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler {
setAdText(getAdText(gotoData.source, targets.length)).
createPopup();
if (gotoData.listUpdaterTask != null) {
gotoData.listUpdaterTask.init((AbstractPopup)popup, list);
gotoData.listUpdaterTask.init((AbstractPopup)popup, list, usageView);
ProgressManager.getInstance().run(gotoData.listUpdaterTask);
}
popup.showInBestPositionFor(editor);
@@ -46,6 +46,9 @@ import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.JDOMUtil;
@@ -60,6 +63,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.ui.LightweightHint;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.*;
import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -910,19 +914,36 @@ public class FindUtil {
boolean shouldReplace(TextRange range, String replace);
}
public static void showInUsageView(PsiElement sourceElement, PsiElement[] targets, String title, Project project) {
public static UsageView showInUsageView(PsiElement sourceElement, final 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);
final UsageInfoToUsageConverter.TargetElementsDescriptor targetElementsDescriptor =
sourceElement != null ? new UsageInfoToUsageConverter.TargetElementsDescriptor(sourceElement)
: new UsageInfoToUsageConverter.TargetElementsDescriptor(PsiElement.EMPTY_ARRAY);
final Usage[] usages = {UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(targets[0]))};
final UsageView view =
UsageViewManager.getInstance(project).showUsages(usageTargets, usages, presentation);
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Updating Usage View ...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
for (int i = 1; i < targets.length; i++) {
if (((UsageViewImpl)view).isDisposed()) break;
final PsiElement target = targets[i];
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final Usage usage = UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(target));
view.appendUsage(usage);
}
});
}
}
});
return view;
}
}
@@ -985,6 +985,10 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra
}
}
public boolean isDisposed() {
return isDisposed;
}
private void showNode(@NotNull final UsageNode node) {
if (!myPresentation.isDetachedMode()) {
UIUtil.invokeLaterIfNeeded(new Runnable() {