Consumer<Boolean> (Project project, @NlsContexts.ProgressTitle String progressTitle, AtomicReference<? extends CancellablePromise<?>> promiseRef, Editor editor) { AtomicReference<Consumer<Boolean>> stopActionRef = new AtomicReference<>(); Consumer<Boolean> originalStopAction = (cancel) -> { stopActionRef.set(null); if (cancel) { CancellablePromise<?> promise = promiseRef.get(); if (promise != null) { promise.cancel(); } } }; if (progressTitle == null) { stopActionRef.set(originalStopAction); } else { final Disposable disposable = Disposer.newDisposable(); Disposer.register(project, disposable); JBLoadingPanel loadingPanel = new JBLoadingPanel(null, panel -> new LoadingDecorator(panel, disposable, 0, false, new AsyncProcessIcon("ShowParameterInfo")) { @Override protected NonOpaquePanel customizeLoadingLayer(JPanel parent, JLabel text, AnimatedIcon icon) { parent.setLayout(new FlowLayout(FlowLayout.LEFT)); final NonOpaquePanel result = new NonOpaquePanel(); result.add(icon); parent.add(result); return result; } }); loadingPanel.add(new JBLabel(EmptyIcon.ICON_18)); loadingPanel.add(new JBLabel(progressTitle)); ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(loadingPanel, null) .setProject(project) .setCancelCallback(() -> { Consumer<Boolean> stopAction = stopActionRef.get(); if (stopAction != null) { stopAction.accept(true); } return true; }); JBPopup popup = builder.createPopup(); Disposer.register(disposable, popup); ScheduledFuture<?> showPopupFuture = EdtScheduledExecutorService.getInstance().schedule(() -> { if (!popup.isDisposed() && !popup.isVisible() && !editor.isDisposed()) { RelativePoint popupPosition = JBPopupFactory.getInstance().guessBestPopupLocation(editor); loadingPanel.startLoading(); popup.show(popupPosition); } }, ModalityState.defaultModalityState(), DEFAULT_PROGRESS_POPUP_DELAY_MS, TimeUnit.MILLISECONDS); stopActionRef.set((cancel) -> { try { loadingPanel.stopLoading(); originalStopAction.accept(cancel); } finally { showPopupFuture.cancel(false); UIUtil.invokeLaterIfNeeded(() -> { if (popup.isVisible()) { popup.setUiVisible(false); } Disposer.dispose(disposable); }); } }); } return stopActionRef.get(); }