void (@Nullable VirtualFile sourceRoot, @Nullable VirtualFile oldSelection, boolean forceIncludeAll) { if (myProject.isDisposed()) return; ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); JComboBox<DirectoryChooser.ItemWrapper> comboBox = getComboBox(); final ComboBoxModel<DirectoryChooser.ItemWrapper> model = comboBox.getModel(); DirectoryChooser.ItemWrapper selectedItem = (DirectoryChooser.ItemWrapper)comboBox.getSelectedItem(); final ArrayList<DirectoryChooser.ItemWrapper> items = new ArrayList<>(); record NonBlockingSelectionResult( @Nullable DirectoryChooser.ItemWrapper selection, @Nullable String message, @NlsSafe @Nullable String relativeSrcPath ) { } ReadAction .nonBlocking(() -> { final LinkedHashSet<PsiDirectory> targetDirectories = new LinkedHashSet<>(); final HashMap<PsiDirectory, String> pathsToCreate = new HashMap<>(); CommonMoveClassesOrPackagesUtil .buildDirectoryList(new PackageWrapper(PsiManager.getInstance(myProject), getTargetPackage()), mySourceRoots, targetDirectories, pathsToCreate); if (!forceIncludeAll && targetDirectories.size() > pathsToCreate.size()) { targetDirectories.removeAll(pathsToCreate.keySet()); } DirectoryChooser.ItemWrapper initial = null; DirectoryChooser.ItemWrapper oldOne = null; for (PsiDirectory targetDirectory : targetDirectories) { DirectoryChooser.ItemWrapper itemWrapper = new DirectoryChooser.ItemWrapper(targetDirectory, pathsToCreate.get(targetDirectory)); items.add(itemWrapper); final VirtualFile sourceRootForFile = fileIndex.getSourceRootForFile(targetDirectory.getVirtualFile()); if (Comparing.equal(sourceRootForFile, sourceRoot)) { initial = itemWrapper; } else if (Comparing.equal(sourceRootForFile, oldSelection)) { oldOne = itemWrapper; } } if (myLeaveInTheSameRoot) { items.add(DirectoryChooser.ItemWrapper.NULL); } final DirectoryChooser.ItemWrapper selection = chooseSelection(sourceRoot, fileIndex, items, initial, oldOne); String relativeSrcPath = sourceRoot != null ? ProjectUtil.calcRelativeToProjectPath(sourceRoot, myProject, true, false, true) : null; if (model instanceof CollectionComboBoxModel) { boolean sameModel = model.getSize() == items.size(); if (sameModel) { for (int i = 0; i < items.size(); i++) { final DirectoryChooser.ItemWrapper oldItem = model.getElementAt(i); final DirectoryChooser.ItemWrapper itemWrapper = items.get(i); if (!areItemsEquivalent(oldItem, itemWrapper)) { sameModel = false; break; } } } if (sameModel && areItemsEquivalent(selectedItem, selection)) { return new NonBlockingSelectionResult(NO_UPDATE_REQUIRED, null, relativeSrcPath); } } return new NonBlockingSelectionResult(selection, getUpdateErrorMessage(fileIndex, selection), relativeSrcPath); }) .expireWith(this) .finishOnUiThread(ModalityState.stateForComponent(this), result -> { DirectoryChooser.ItemWrapper selection = result.selection; if (selection == NO_UPDATE_REQUIRED) return; myUpdateErrorMessage.accept(result.message); items.sort((o1, o2) -> { if (o1 == o2) return 0; if (o1 == DirectoryChooser.ItemWrapper.NULL) return -1; if (o2 == DirectoryChooser.ItemWrapper.NULL) return 1; return o1.getRelativeToProjectPath().compareToIgnoreCase(o2.getRelativeToProjectPath()); }); comboBox.setModel(new CollectionComboBoxModel<>(items, selection)); final Component root = SwingUtilities.getRoot(comboBox); if (root instanceof Window) { final Dimension preferredSize = root.getPreferredSize(); if (preferredSize.getWidth() > root.getSize().getWidth()) { root.setSize(preferredSize); } } updateTooltipText(result.relativeSrcPath); }) .submit(AppExecutorUtil.getAppExecutorService()); }