use of com.intellij.openapi.ui.popup.JBPopup in project intellij-community by JetBrains.
the class PsiElementListNavigator method openTargets.
public static void openTargets(MouseEvent e, NavigatablePsiElement[] targets, String title, final String findUsagesTitle, ListCellRenderer listRenderer, @Nullable ListBackgroundUpdaterTask listUpdaterTask) {
JBPopup popup = navigateOrCreatePopup(targets, title, findUsagesTitle, listRenderer, listUpdaterTask);
if (popup != null) {
if (listUpdaterTask != null) {
Alarm alarm = new Alarm(popup);
alarm.addRequest(() -> popup.show(new RelativePoint(e)), 300);
ProgressManager.getInstance().run(listUpdaterTask);
} else {
popup.show(new RelativePoint(e));
}
}
}
use of com.intellij.openapi.ui.popup.JBPopup in project intellij-community by JetBrains.
the class PsiElementListNavigator method navigateOrCreatePopup.
/**
* listUpdaterTask should be started after alarm is initialized so one-item popup won't blink
*/
@Nullable
public static JBPopup navigateOrCreatePopup(@NotNull final NavigatablePsiElement[] targets, final String title, final String findUsagesTitle, final ListCellRenderer listRenderer, @Nullable final ListBackgroundUpdaterTask listUpdaterTask, @NotNull final Consumer<Object[]> consumer) {
if (targets.length == 0)
return null;
if (targets.length == 1 && (listUpdaterTask == null || listUpdaterTask.isFinished())) {
consumer.consume(targets);
return null;
}
final CollectionListModel<NavigatablePsiElement> model = new CollectionListModel<>(targets);
final JBList list = new JBList(model);
HintUpdateSupply.installSimpleHintUpdateSupply(list);
list.setTransferHandler(new TransferHandler() {
@Nullable
@Override
protected Transferable createTransferable(JComponent c) {
final Object[] selectedValues = list.getSelectedValues();
final PsiElement[] copy = new PsiElement[selectedValues.length];
for (int i = 0; i < selectedValues.length; i++) {
copy[i] = (PsiElement) selectedValues[i];
}
return new PsiCopyPasteManager.MyTransferable(copy);
}
@Override
public int getSourceActions(JComponent c) {
return COPY;
}
});
list.setCellRenderer(listRenderer);
list.setFont(EditorUtil.getEditorFont());
final PopupChooserBuilder builder = new PopupChooserBuilder(list);
if (listRenderer instanceof PsiElementListCellRenderer) {
((PsiElementListCellRenderer) listRenderer).installSpeedSearch(builder);
}
PopupChooserBuilder popupChooserBuilder = builder.setTitle(title).setMovable(true).setResizable(true).setItemChoosenCallback(() -> {
int[] ids = list.getSelectedIndices();
if (ids == null || ids.length == 0)
return;
Object[] selectedElements = list.getSelectedValues();
consumer.consume(selectedElements);
}).setCancelCallback(() -> {
HintUpdateSupply.hideHint(list);
if (listUpdaterTask != null) {
listUpdaterTask.cancelTask();
}
return true;
});
final Ref<UsageView> usageView = new Ref<>();
if (findUsagesTitle != null) {
popupChooserBuilder = popupChooserBuilder.setCouldPin(popup -> {
final List<NavigatablePsiElement> items = model.getItems();
usageView.set(FindUtil.showInUsageView(null, items.toArray(new PsiElement[items.size()]), findUsagesTitle, targets[0].getProject()));
popup.cancel();
return false;
});
}
final JBPopup popup = popupChooserBuilder.createPopup();
builder.getScrollPane().setBorder(null);
builder.getScrollPane().setViewportBorder(null);
if (listUpdaterTask != null) {
listUpdaterTask.init((AbstractPopup) popup, list, usageView);
}
return popup;
}
use of com.intellij.openapi.ui.popup.JBPopup in project intellij-community by JetBrains.
the class ShowImplementationsAction method showImplementations.
protected void showImplementations(@NotNull PsiElement[] impls, @NotNull final Project project, final String text, final Editor editor, final PsiFile file, final PsiElement element, boolean invokedFromEditor, boolean invokedByShortcut) {
if (impls.length == 0)
return;
FeatureUsageTracker.getInstance().triggerFeatureUsed(CODEASSISTS_QUICKDEFINITION_FEATURE);
if (LookupManager.getInstance(project).getActiveLookup() != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CODEASSISTS_QUICKDEFINITION_LOOKUP_FEATURE);
}
int index = 0;
if (invokedFromEditor && file != null && impls.length > 1) {
final VirtualFile virtualFile = file.getVirtualFile();
final PsiFile containingFile = impls[0].getContainingFile();
if (virtualFile != null && containingFile != null && virtualFile.equals(containingFile.getVirtualFile())) {
final PsiFile secondContainingFile = impls[1].getContainingFile();
if (secondContainingFile != containingFile) {
index = 1;
}
}
}
final Ref<UsageView> usageView = new Ref<>();
final String title = CodeInsightBundle.message("implementation.view.title", text);
JBPopup popup = SoftReference.dereference(myPopupRef);
if (popup != null && popup.isVisible() && popup instanceof AbstractPopup) {
final ImplementationViewComponent component = (ImplementationViewComponent) ((AbstractPopup) popup).getComponent();
((AbstractPopup) popup).setCaption(title);
component.update(impls, index);
updateInBackground(editor, element, component, title, (AbstractPopup) popup, usageView);
if (invokedByShortcut) {
((AbstractPopup) popup).focusPreferredComponent();
}
return;
}
final ImplementationViewComponent component = new ImplementationViewComponent(impls, index);
if (component.hasElementsToShow()) {
final PopupUpdateProcessor updateProcessor = new PopupUpdateProcessor(project) {
@Override
public void updatePopup(Object lookupItemObject) {
final PsiElement element = lookupItemObject instanceof PsiElement ? (PsiElement) lookupItemObject : DocumentationManager.getInstance(project).getElementFromLookup(editor, file);
updateElementImplementations(element, editor, project, file);
}
};
popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component.getPreferredFocusableComponent()).setProject(project).addListener(updateProcessor).addUserData(updateProcessor).setDimensionServiceKey(project, DocumentationManager.JAVADOC_LOCATION_AND_SIZE, false).setResizable(true).setMovable(true).setRequestFocus(invokedFromEditor && LookupManager.getActiveLookup(editor) == null).setTitle(title).setCouldPin(popup1 -> {
usageView.set(component.showInUsageView());
popup1.cancel();
myTaskRef = null;
return false;
}).setCancelCallback(() -> {
ImplementationsUpdaterTask task = SoftReference.dereference(myTaskRef);
if (task != null) {
task.cancelTask();
}
return Boolean.TRUE;
}).createPopup();
updateInBackground(editor, element, component, title, (AbstractPopup) popup, usageView);
PopupPositionManager.positionPopupInBestPosition(popup, editor, DataManager.getInstance().getDataContext());
component.setHint(popup, title);
myPopupRef = new WeakReference<>(popup);
}
}
use of com.intellij.openapi.ui.popup.JBPopup in project intellij-community by JetBrains.
the class ShowUsagesAction method showElementUsages.
private void showElementUsages(final Editor editor, @NotNull final RelativePoint popupPosition, @NotNull final FindUsagesHandler handler, final int maxUsages, @NotNull final FindUsagesOptions options) {
ApplicationManager.getApplication().assertIsDispatchThread();
final UsageViewSettings usageViewSettings = UsageViewSettings.getInstance();
final UsageViewSettings savedGlobalSettings = new UsageViewSettings();
savedGlobalSettings.loadState(usageViewSettings);
usageViewSettings.loadState(myUsageViewSettings);
final Project project = handler.getProject();
UsageViewManager manager = UsageViewManager.getInstance(project);
FindUsagesManager findUsagesManager = ((FindManagerImpl) FindManager.getInstance(project)).getFindUsagesManager();
final UsageViewPresentation presentation = findUsagesManager.createPresentation(handler, options);
presentation.setDetachedMode(true);
UsageViewImpl usageView = (UsageViewImpl) manager.createUsageView(UsageTarget.EMPTY_ARRAY, Usage.EMPTY_ARRAY, presentation, null);
if (editor != null) {
PsiReference reference = TargetElementUtil.findReference(editor);
if (reference != null) {
UsageInfo2UsageAdapter origin = new UsageInfo2UsageAdapter(new UsageInfo(reference));
usageView.setOriginUsage(origin);
}
}
Disposer.register(usageView, () -> {
myUsageViewSettings.loadState(usageViewSettings);
usageViewSettings.loadState(savedGlobalSettings);
});
final MyTable table = new MyTable();
final AsyncProcessIcon processIcon = new AsyncProcessIcon("xxx");
addUsageNodes(usageView.getRoot(), usageView, new ArrayList<>());
final List<Usage> usages = new ArrayList<>();
final Set<UsageNode> visibleNodes = new LinkedHashSet<>();
final List<UsageNode> data = collectData(usages, visibleNodes, usageView, presentation);
final AtomicInteger outOfScopeUsages = new AtomicInteger();
setTableModel(table, usageView, data, outOfScopeUsages, options.searchScope);
boolean isPreviewMode = Boolean.TRUE == PreviewManager.SERVICE.preview(handler.getProject(), UsagesPreviewPanelProvider.ID, Pair.create(usageView, table), false);
Runnable itemChosenCallback = prepareTable(table, editor, popupPosition, handler, maxUsages, options, isPreviewMode);
@Nullable final JBPopup popup = isPreviewMode ? null : createUsagePopup(usages, visibleNodes, handler, editor, popupPosition, maxUsages, usageView, options, table, itemChosenCallback, presentation, processIcon);
if (popup != null) {
Disposer.register(popup, usageView);
// show popup only if find usages takes more than 300ms, otherwise it would flicker needlessly
Alarm alarm = new Alarm(usageView);
alarm.addRequest(() -> showPopupIfNeedTo(popup, popupPosition), 300);
}
final PingEDT pingEDT = new PingEDT("Rebuild popup in EDT", o -> popup != null && popup.isDisposed(), 100, () -> {
if (popup != null && popup.isDisposed())
return;
final List<UsageNode> nodes = new ArrayList<>();
List<Usage> copy;
synchronized (usages) {
// open up popup as soon as several usages 've been found
if (popup != null && !popup.isVisible() && (usages.size() <= 1 || !showPopupIfNeedTo(popup, popupPosition))) {
return;
}
addUsageNodes(usageView.getRoot(), usageView, nodes);
copy = new ArrayList<>(usages);
}
rebuildTable(usageView, copy, nodes, table, popup, presentation, popupPosition, !processIcon.isDisposed(), outOfScopeUsages, options.searchScope);
});
final MessageBusConnection messageBusConnection = project.getMessageBus().connect(usageView);
messageBusConnection.subscribe(UsageFilteringRuleProvider.RULES_CHANGED, pingEDT::ping);
final UsageTarget[] myUsageTarget = { new PsiElement2UsageTargetAdapter(handler.getPsiElement()) };
Processor<Usage> collect = usage -> {
if (!UsageViewManagerImpl.isInScope(usage, options.searchScope)) {
if (outOfScopeUsages.getAndIncrement() == 0) {
visibleNodes.add(USAGES_OUTSIDE_SCOPE_NODE);
usages.add(USAGES_OUTSIDE_SCOPE_SEPARATOR);
}
return true;
}
synchronized (usages) {
if (visibleNodes.size() >= maxUsages)
return false;
if (UsageViewManager.isSelfUsage(usage, myUsageTarget))
return true;
UsageNode node = ReadAction.compute(() -> usageView.doAppendUsage(usage));
usages.add(usage);
if (node != null) {
visibleNodes.add(node);
boolean continueSearch = true;
if (visibleNodes.size() == maxUsages) {
visibleNodes.add(MORE_USAGES_SEPARATOR_NODE);
usages.add(MORE_USAGES_SEPARATOR);
continueSearch = false;
}
pingEDT.ping();
return continueSearch;
}
}
return true;
};
final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, handler.getPrimaryElements(), handler.getSecondaryElements(), collect, options, () -> ApplicationManager.getApplication().invokeLater(() -> {
Disposer.dispose(processIcon);
Container parent = processIcon.getParent();
if (parent != null) {
parent.remove(processIcon);
parent.repaint();
}
// repaint title
pingEDT.ping();
synchronized (usages) {
if (visibleNodes.isEmpty()) {
if (usages.isEmpty()) {
String text = UsageViewBundle.message("no.usages.found.in", searchScopePresentableName(options));
hint(editor, text, handler, popupPosition, maxUsages, options, false);
cancel(popup);
}
// else all usages filtered out
} else if (visibleNodes.size() == 1) {
if (usages.size() == 1) {
//the only usage
Usage usage = visibleNodes.iterator().next().getUsage();
if (usage == USAGES_OUTSIDE_SCOPE_SEPARATOR) {
hint(editor, UsageViewManagerImpl.outOfScopeMessage(outOfScopeUsages.get(), options.searchScope), handler, popupPosition, maxUsages, options, true);
} else {
String message = UsageViewBundle.message("show.usages.only.usage", searchScopePresentableName(options));
navigateAndHint(usage, message, handler, popupPosition, maxUsages, options);
}
cancel(popup);
} else {
assert usages.size() > 1 : usages;
// usage view can filter usages down to one
Usage visibleUsage = visibleNodes.iterator().next().getUsage();
if (areAllUsagesInOneLine(visibleUsage, usages)) {
String hint = UsageViewBundle.message("all.usages.are.in.this.line", usages.size(), searchScopePresentableName(options));
navigateAndHint(visibleUsage, hint, handler, popupPosition, maxUsages, options);
cancel(popup);
}
}
} else {
if (popup != null) {
String title = presentation.getTabText();
boolean shouldShowMoreSeparator = visibleNodes.contains(MORE_USAGES_SEPARATOR_NODE);
String fullTitle = getFullTitle(usages, title, shouldShowMoreSeparator, visibleNodes.size() - (shouldShowMoreSeparator ? 1 : 0), false);
((AbstractPopup) popup).setCaption(fullTitle);
}
}
}
}, project.getDisposed()));
if (popup != null) {
Disposer.register(popup, indicator::cancel);
}
}
use of com.intellij.openapi.ui.popup.JBPopup in project intellij-community by JetBrains.
the class ShowUsagesAction method createUsagePopup.
@NotNull
private JBPopup createUsagePopup(@NotNull final List<Usage> usages, @NotNull Set<UsageNode> visibleNodes, @NotNull final FindUsagesHandler handler, final Editor editor, @NotNull final RelativePoint popupPosition, final int maxUsages, @NotNull final UsageViewImpl usageView, @NotNull final FindUsagesOptions options, @NotNull final JTable table, @NotNull final Runnable itemChoseCallback, @NotNull final UsageViewPresentation presentation, @NotNull final AsyncProcessIcon processIcon) {
ApplicationManager.getApplication().assertIsDispatchThread();
PopupChooserBuilder builder = new PopupChooserBuilder(table);
final String title = presentation.getTabText();
if (title != null) {
String result = getFullTitle(usages, title, false, visibleNodes.size() - 1, true);
builder.setTitle(result);
builder.setAdText(getSecondInvocationTitle(options, handler));
}
builder.setMovable(true).setResizable(true);
builder.setMovable(true).setResizable(true);
builder.setItemChoosenCallback(itemChoseCallback);
final JBPopup[] popup = new JBPopup[1];
KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut();
if (shortcut != null) {
new DumbAwareAction() {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
cancel(popup[0]);
showDialogAndFindUsages(handler, popupPosition, editor, maxUsages);
}
@Override
public boolean startInTransaction() {
return true;
}
}.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
}
shortcut = getShowUsagesShortcut();
if (shortcut != null) {
new DumbAwareAction() {
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
cancel(popup[0]);
searchEverywhere(options, handler, editor, popupPosition, maxUsages);
}
@Override
public boolean startInTransaction() {
return true;
}
}.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table);
}
InplaceButton settingsButton = createSettingsButton(handler, popupPosition, editor, maxUsages, () -> cancel(popup[0]));
ActiveComponent spinningProgress = new ActiveComponent.Adapter() {
@Override
public JComponent getComponent() {
return processIcon;
}
};
final DefaultActionGroup pinGroup = new DefaultActionGroup();
final ActiveComponent pin = createPinButton(handler, usageView, options, popup, pinGroup);
builder.setCommandButton(new CompositeActiveComponent(spinningProgress, settingsButton, pin));
DefaultActionGroup toolbar = new DefaultActionGroup();
usageView.addFilteringActions(toolbar);
toolbar.add(UsageGroupingRuleProviderImpl.createGroupByFileStructureAction(usageView));
ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.USAGE_VIEW_TOOLBAR, toolbar, true);
actionToolbar.setReservePlaceAutoPopupIcon(false);
final JComponent toolBar = actionToolbar.getComponent();
toolBar.setOpaque(false);
builder.setSettingButton(toolBar);
builder.setCancelKeyEnabled(false);
popup[0] = builder.createPopup();
JComponent content = popup[0].getContent();
myWidth = (int) (toolBar.getPreferredSize().getWidth() + new JLabel(getFullTitle(usages, title, false, visibleNodes.size() - 1, true)).getPreferredSize().getWidth() + settingsButton.getPreferredSize().getWidth());
myWidth = -1;
for (AnAction action : toolbar.getChildren(null)) {
action.unregisterCustomShortcutSet(usageView.getComponent());
action.registerCustomShortcutSet(action.getShortcutSet(), content);
}
for (AnAction action : pinGroup.getChildren(null)) {
action.unregisterCustomShortcutSet(usageView.getComponent());
action.registerCustomShortcutSet(action.getShortcutSet(), content);
}
return popup[0];
}
Aggregations