JBPopup (@Nullable Project project, @NlsContexts.PopupTitle String title, String initialText, @NotNull PsiDirectory directory, CreateGroupHandler validator, Consumer<? super List<PsiElement>> consumer) { List<CompletionItem> variants = collectSuggestedDirectories(directory); DirectoriesWithCompletionPopupPanel contentPanel = new DirectoriesWithCompletionPopupPanel(variants); JTextField nameField = contentPanel.getTextField(); nameField.getDocument().addDocumentListener(new DocumentAdapter() { @Override public void textChanged(@NotNull DocumentEvent event) { final String text = nameField.getText(); validator.checkInput(text); String errorText = validator.getErrorText(text); String warningText = validator.getWarningText(text); if (errorText != null) { contentPanel.setError(errorText); } else if (warningText != null) { contentPanel.setWarning(warningText); } else if (contentPanel.hasError()) { contentPanel.setError(null); } } }); nameField.setText(initialText); JBPopup popup = NewItemPopupUtil.createNewItemPopup(title, contentPanel, nameField); contentPanel.setApplyAction(event -> { for (CompletionItem it : contentPanel.getSelectedItems()) { CreateDirectoryUsageCollector.logCompletionVariantChosen(project, it.contributor.getClass()); } // if there are selected suggestions, we need to create the selected folders (not the path in the text field) List<Pair<String, JpsModuleSourceRootType<?>>> toCreate = ContainerUtil.map(contentPanel.getSelectedItems(), item -> Pair.create(item.relativePath, item.rootType)); // when there are no selected suggestions, simply create the directory with the path from the text field if (toCreate.isEmpty()) toCreate = Collections.singletonList(Pair.create(nameField.getText(), null)); List<PsiElement> created = createDirectories(toCreate, validator); if (created != null) { popup.closeOk(event); consumer.accept(created); } else { for (Pair<String, JpsModuleSourceRootType<?>> dir : toCreate) { String errorMessage = validator.getErrorText(dir.first); if (errorMessage != null) { contentPanel.setError(errorMessage); break; } } } }); contentPanel.addTemplatesVisibilityListener(visible -> { // The re-layout should be delayed since we are in the middle of model changes processing and not all components updated their states SwingUtilities.invokeLater(() -> popup.pack(false, true)); }); return popup; }