'unmark root' action: allow user to cancel exclusion if excluded folder is selected (IDEA-23537)

This commit is contained in:
nik
2014-07-18 12:31:07 +04:00
parent d61da37eda
commit f17f398f24
4 changed files with 97 additions and 26 deletions
@@ -21,6 +21,7 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -32,11 +33,13 @@ public class MarkExcludeRootAction extends MarkRootActionBase {
public void actionPerformed(AnActionEvent e) {
VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
String message = files.length == 1 ? FileUtil.toSystemDependentName(files[0].getPath()) : files.length + " selected files";
final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT), getPromptText(message), "Mark as Excluded",
Messages.getQuestionIcon());
if (rc != Messages.OK) {
return;
if (Registry.is("ide.hide.excluded.files")) {
String message = files.length == 1 ? FileUtil.toSystemDependentName(files[0].getPath()) : files.length + " selected files";
final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT), getPromptText(message), "Mark as Excluded",
Messages.getQuestionIcon());
if (rc != Messages.OK) {
return;
}
}
super.actionPerformed(e);
}
@@ -22,7 +22,9 @@ import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.DirectoryIndex;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -38,23 +40,24 @@ import java.util.List;
public abstract class MarkRootActionBase extends DumbAwareAction {
@Override
public void actionPerformed(AnActionEvent e) {
final Module module = e.getData(LangDataKeys.MODULE);
VirtualFile[] vFiles = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
if (module == null || vFiles == null) {
VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
final Module module = getModule(e, files);
if (module == null) {
return;
}
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
for (VirtualFile vFile : vFiles) {
ContentEntry entry = findContentEntry(model, vFile);
for (VirtualFile file : files) {
ContentEntry entry = findContentEntry(model, file);
if (entry != null) {
final SourceFolder[] sourceFolders = entry.getSourceFolders();
for (SourceFolder sourceFolder : sourceFolders) {
if (Comparing.equal(sourceFolder.getFile(), vFile)) {
if (Comparing.equal(sourceFolder.getFile(), file)) {
entry.removeSourceFolder(sourceFolder);
break;
}
}
modifyRoots(vFile, entry);
modifyRoots(file, entry);
}
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@@ -66,7 +69,7 @@ public abstract class MarkRootActionBase extends DumbAwareAction {
});
}
protected abstract void modifyRoots(VirtualFile vFile, ContentEntry entry);
protected abstract void modifyRoots(VirtualFile file, ContentEntry entry);
@Nullable
public static ContentEntry findContentEntry(@NotNull ModuleRootModel model, @NotNull VirtualFile vFile) {
@@ -82,21 +85,22 @@ public abstract class MarkRootActionBase extends DumbAwareAction {
@Override
public void update(AnActionEvent e) {
Module module = e.getData(LangDataKeys.MODULE);
RootsSelection selection = getSelection(e);
boolean enabled = module != null && (!selection.mySelectedRoots.isEmpty() || !selection.mySelectedDirectories.isEmpty()) && isEnabled(selection, module);
e.getPresentation().setVisible(enabled);
e.getPresentation().setEnabled(enabled);
doUpdate(e, e.getData(LangDataKeys.MODULE), selection);
}
protected void doUpdate(@NotNull AnActionEvent e, @Nullable Module module, @NotNull RootsSelection selection) {
boolean enabled = module != null && (!selection.mySelectedRoots.isEmpty() || !selection.mySelectedDirectories.isEmpty())
&& selection.mySelectedExcludeRoots.isEmpty() && isEnabled(selection, module);
e.getPresentation().setEnabledAndVisible(enabled);
}
protected abstract boolean isEnabled(@NotNull RootsSelection selection, @NotNull Module module);
protected static RootsSelection getSelection(AnActionEvent e) {
Module module = e.getData(LangDataKeys.MODULE);
VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
if (module == null || files == null) {
return RootsSelection.EMPTY;
}
Module module = getModule(e, files);
if (module == null) return RootsSelection.EMPTY;
RootsSelection selection = new RootsSelection();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(module.getProject()).getFileIndex();
@@ -105,7 +109,14 @@ public abstract class MarkRootActionBase extends DumbAwareAction {
return RootsSelection.EMPTY;
}
if (!fileIndex.isInContent(file)) {
return RootsSelection.EMPTY;
ExcludeFolder excludeFolder = ProjectRootsUtil.findExcludeFolder(module, file);
if (excludeFolder != null) {
selection.mySelectedExcludeRoots.add(excludeFolder);
continue;
}
else {
return RootsSelection.EMPTY;
}
}
SourceFolder folder;
if (Comparing.equal(fileIndex.getSourceRootForFile(file), file) && ((folder = ProjectRootsUtil.findSourceFolder(module, file)) != null)) {
@@ -121,10 +132,39 @@ public abstract class MarkRootActionBase extends DumbAwareAction {
return selection;
}
@Nullable
private static Module getModule(@NotNull AnActionEvent e, @Nullable VirtualFile[] files) {
if (files == null) return null;
Module module = e.getData(LangDataKeys.MODULE);
if (module == null) {
module = findParentModule(e.getProject(), files);
}
return module;
}
@Nullable
private static Module findParentModule(@Nullable Project project, @NotNull VirtualFile[] files) {
if (project == null) return null;
Module result = null;
DirectoryIndex index = DirectoryIndex.getInstance(project);
for (VirtualFile file : files) {
Module module = index.getInfoForFile(file).getModule();
if (module == null) return null;
if (result == null) {
result = module;
}
else if (!result.equals(module)) {
return null;
}
}
return result;
}
protected static class RootsSelection {
public static final RootsSelection EMPTY = new RootsSelection();
public List<SourceFolder> mySelectedRoots = new ArrayList<SourceFolder>();
public List<ExcludeFolder> mySelectedExcludeRoots = new ArrayList<ExcludeFolder>();
public List<VirtualFile> mySelectedDirectories = new ArrayList<VirtualFile>();
public boolean myHaveSelectedFilesUnderSourceRoots;
}
@@ -18,12 +18,15 @@ package com.intellij.ide.projectView.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ExcludeFolder;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.roots.ui.configuration.ModuleSourceRootEditHandler;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.util.Set;
@@ -33,9 +36,16 @@ import java.util.Set;
*/
public class UnmarkRootAction extends MarkRootActionBase {
@Override
public void update(AnActionEvent e) {
super.update(e);
RootsSelection selection = getSelection(e);
protected void doUpdate(@NotNull AnActionEvent e, @Nullable Module module, @NotNull RootsSelection selection) {
if (!Registry.is("ide.hide.excluded.files") && !selection.mySelectedExcludeRoots.isEmpty()
&& selection.mySelectedDirectories.isEmpty() && selection.mySelectedRoots.isEmpty()) {
e.getPresentation().setEnabledAndVisible(true);
e.getPresentation().setText("Cancel Exclusion");
return;
}
super.doUpdate(e, module, selection);
Set<JpsModuleSourceRootType<?>> selectedRootTypes = new HashSet<JpsModuleSourceRootType<?>>();
for (SourceFolder root : selection.mySelectedRoots) {
selectedRootTypes.add(root.getRootType());
@@ -60,6 +70,12 @@ public class UnmarkRootAction extends MarkRootActionBase {
return selection.mySelectedDirectories.isEmpty() && !selection.mySelectedRoots.isEmpty();
}
protected void modifyRoots(VirtualFile vFile, ContentEntry entry) {
protected void modifyRoots(VirtualFile file, ContentEntry entry) {
for (ExcludeFolder excludeFolder : entry.getExcludeFolders()) {
if (file.equals(excludeFolder.getFile())) {
entry.removeExcludeFolder(excludeFolder);
break;
}
}
}
}
@@ -109,4 +109,16 @@ public class ProjectRootsUtil {
}
return null;
}
@Nullable
public static ExcludeFolder findExcludeFolder(@NotNull Module module, @NotNull VirtualFile root) {
for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
for (ExcludeFolder folder : entry.getExcludeFolders()) {
if (root.equals(folder.getFile())) {
return folder;
}
}
}
return null;
}
}