void (@NotNull Project project, @Nullable PsiDirectory targetDirectory, @NotNull Consumer<? super @NlsContexts.DialogMessage String> errorMessageUpdater, @NotNull EditorComboBox editorComboBox) { myProject = project; myInitialTargetDirectory = targetDirectory; mySourceRoots = getSourceRoots(project, targetDirectory); myUpdateErrorMessage = errorMessageUpdater; String leaveInSameSourceRoot = JavaBundle.message("leave.in.same.source.root.item"); ComboboxSpeedSearch search = new ComboboxSpeedSearch(getComboBox(), null) { @Override protected String getElementText(Object element) { if (element == DirectoryChooser.ItemWrapper.NULL) return leaveInSameSourceRoot; if (element instanceof DirectoryChooser.ItemWrapper) { final VirtualFile virtualFile = ((DirectoryChooser.ItemWrapper)element).getDirectory().getVirtualFile(); final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project); if (module != null) { return module.getName(); } } return super.getElementText(element); } }; search.setupListeners(); getComboBox().setRenderer(SimpleListCellRenderer.<DirectoryChooser.ItemWrapper>create( (label, itemWrapper, index) -> { if (itemWrapper != DirectoryChooser.ItemWrapper.NULL && itemWrapper != null) { label.setIcon(itemWrapper.getIcon()); label.setText(itemWrapper.getRelativeToProjectPath()); } else { label.setText(leaveInSameSourceRoot); } })); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); final VirtualFile sourceRoot = targetDirectory != null ? fileIndex.getSourceRootForFile(targetDirectory.getVirtualFile()) : null; myLeaveInTheSameRoot = targetDirectory == null || sourceRoot != null && !fileIndex.isInLibrarySource(sourceRoot); addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { final ComboBoxModel<DirectoryChooser.ItemWrapper> model = getComboBox().getModel(); VirtualFile root = CommonMoveClassesOrPackagesUtil.chooseSourceRoot( new PackageWrapper(PsiManager.getInstance(project), getTargetPackage()), mySourceRoots, targetDirectory ); if (root == null) return; List<DirectoryChooser.ItemWrapper> items = new ArrayList<>(model.getSize()); for (int i = 0; i < model.getSize(); i++) items.add(model.getElementAt(i)); record NonBlockingResult(@NotNull VirtualFile root, @Nullable DirectoryChooser.ItemWrapper item) { } ReadAction .nonBlocking(() -> new NonBlockingResult( root, ContainerUtil.find(items, item -> item != DirectoryChooser.ItemWrapper.NULL && Comparing.equal(fileIndex.getSourceRootForFile(item.getDirectory().getVirtualFile()), root) ) )) .expireWith(DestinationFolderComboBox.this) .finishOnUiThread(ModalityState.current(), result -> { if (result.item != null) { getComboBox().setSelectedItem(result.item); getComboBox().repaint(); } setComboboxModel(result.root, result.root, true); }) .submit(AppExecutorUtil.getAppExecutorService()); } }); final AtomicReference<VirtualFile> selection = new AtomicReference<>(sourceRoot); editorComboBox.addDocumentListener(new DocumentListener() { @Override public void documentChanged(@NotNull DocumentEvent e) { JComboBox comboBox = getComboBox(); DirectoryChooser.ItemWrapper selectedItem = (DirectoryChooser.ItemWrapper)comboBox.getSelectedItem(); VirtualFile initialTargetDirectorySourceRoot = selectedItem != null && selectedItem != DirectoryChooser.ItemWrapper.NULL ? fileIndex.getSourceRootForFile(selectedItem.getDirectory().getVirtualFile()) : sourceRoot; setComboboxModel(initialTargetDirectorySourceRoot, selection.get(), false); } }); setComboboxModel(sourceRoot, selection.get(), false); getComboBox().addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Object selectedItem = getComboBox().getSelectedItem(); record NonBlockingResult(@Nullable String error, @NlsSafe @Nullable String relativeSrcPath) { } ReadAction .nonBlocking(() -> { if (selectedItem instanceof DirectoryChooser.ItemWrapper && selectedItem != DirectoryChooser.ItemWrapper.NULL) { PsiDirectory directory = ((DirectoryChooser.ItemWrapper)selectedItem).getDirectory(); if (directory != null) { selection.set(fileIndex.getSourceRootForFile(directory.getVirtualFile())); } } String relativeSrcPath = null; if (sourceRoot != null) { relativeSrcPath = ProjectUtil.calcRelativeToProjectPath(sourceRoot, myProject, true, false, true); } return new NonBlockingResult(getUpdateErrorMessage(fileIndex, selectedItem), relativeSrcPath); }) .expireWith(DestinationFolderComboBox.this) .finishOnUiThread(ModalityState.stateForComponent(getComboBox()), (result) -> { myUpdateErrorMessage.accept(result.error); updateTooltipText(result.relativeSrcPath); }).submit(AppExecutorUtil.getAppExecutorService()); } }); }