void (@Nullable PopupState<Balloon> state) { Disposable balloonDisposable = Disposer.newDisposable(); Function<String, String> pathToErrorMessage = path -> getErrorIfBadFolderPathForStoringInArbitraryFile(myProject, path); RunConfigurationStoragePopup popup = new RunConfigurationStoragePopup(myProject, getDotIdeaStoragePath(myProject), pathToErrorMessage, balloonDisposable); Balloon balloon = JBPopupFactory.getInstance().createBalloonBuilder(popup.getMainPanel()) .setDialogMode(true) .setBorderInsets(JBUI.insets(20, 15, 10, 15)) .setFillColor(UIUtil.getPanelBackground()) .setHideOnAction(false) .setHideOnLinkClick(false) .setHideOnKeyOutside(false) // otherwise any keypress in file chooser hides the underlying balloon .setBlockClicksThroughBalloon(true) .setRequestFocus(true) .createBalloon(); balloon.setAnimationEnabled(false); String path = myRCStorageType == RCStorageType.DotIdeaFolder ? getDotIdeaStoragePath(myProject) : StringUtil.notNullize(myFolderPathIfStoredInArbitraryFile); Set<String> pathsToSuggest = new LinkedHashSet<>(); if (getErrorIfBadFolderPathForStoringInArbitraryFile(myProject, path) == null) { pathsToSuggest.add(path); } if (myRCStorageTypeInitial == RCStorageType.ArbitraryFileInProject && myFolderPathIfStoredInArbitraryFileInitial != null) { pathsToSuggest.add(myFolderPathIfStoredInArbitraryFileInitial); } pathsToSuggest.add(getDotIdeaStoragePath(myProject)); pathsToSuggest.addAll(getFolderPathsWithinProjectWhereRunConfigurationsStored(myProject)); popup.reset(path, pathsToSuggest, () -> balloon.hide()); balloon.addListener(new JBPopupListener() { @Override public void onClosed(@NotNull LightweightWindowEvent event) { Disposer.dispose(balloonDisposable); String newPath = popup.getPath(); if (!newPath.equals(path)) { applyChangedStoragePath(newPath); if (myOnModifiedRunnable != null) { myOnModifiedRunnable.run(); } } } }); if (state != null) state.prepareToShow(balloon); balloon.show(RelativePoint.getSouthOf(myStoreAsFileCheckBox), Balloon.Position.below); }