show only one confirmation dialog when deleting libraries or modules from Project Structure (IDEA-83808)

This commit is contained in:
nik
2015-10-06 18:25:54 +03:00
parent 7aa7a0b082
commit 488d53a015
11 changed files with 348 additions and 237 deletions
@@ -354,10 +354,20 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
return myModuleModelCommitted;
}
public boolean deleteModule(final Module module) {
ModuleEditor moduleEditor = getModuleEditor(module);
if (moduleEditor == null) return true;
return doRemoveModule(moduleEditor);
public List<Module> deleteModules(final Collection<Module> modules) {
List<Module> deleted = new ArrayList<Module>();
List<ModuleEditor> moduleEditors = new ArrayList<ModuleEditor>();
for (Module module : modules) {
ModuleEditor moduleEditor = getModuleEditor(module);
if (moduleEditor != null) {
deleted.add(module);
moduleEditors.add(moduleEditor);
}
}
if (doRemoveModules(moduleEditors)) {
return deleted;
}
return Collections.emptyList();
}
@@ -464,37 +474,37 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
}
private boolean doRemoveModule(@NotNull ModuleEditor selectedEditor) {
private boolean doRemoveModules(@NotNull List<ModuleEditor> selectedEditors) {
if (selectedEditors.isEmpty()) return true;
String question;
if (myModuleEditors.size() == 1) {
question = ProjectBundle.message("module.remove.last.confirmation");
if (myModuleEditors.size() == selectedEditors.size()) {
question = ProjectBundle.message("module.remove.last.confirmation", selectedEditors.size());
}
else {
question = ProjectBundle.message("module.remove.confirmation", selectedEditor.getModule().getName());
question = ProjectBundle.message("module.remove.confirmation", selectedEditors.get(0).getModule().getName(), selectedEditors.size());
}
int result =
Messages.showYesNoDialog(myProject, question, ProjectBundle.message("module.remove.confirmation.title"), Messages.getQuestionIcon());
Messages.showYesNoDialog(myProject, question, ProjectBundle.message("module.remove.confirmation.title", selectedEditors.size()), Messages.getQuestionIcon());
if (result != Messages.YES) {
return false;
}
// do remove
myModuleEditors.remove(selectedEditor.getModule());
for (ModuleEditor editor : selectedEditors) {
myModuleEditors.remove(editor.getModule());
// destroyProcess removed module
final Module moduleToRemove = selectedEditor.getModule();
// remove all dependencies on the module that is about to be removed
List<ModifiableRootModel> modifiableRootModels = new ArrayList<ModifiableRootModel>();
for (final ModuleEditor moduleEditor : myModuleEditors.values()) {
final ModifiableRootModel modifiableRootModel = moduleEditor.getModifiableRootModelProxy();
ContainerUtil.addIfNotNull(modifiableRootModels, modifiableRootModel);
final Module moduleToRemove = editor.getModule();
// remove all dependencies on the module which is about to be removed
List<ModifiableRootModel> modifiableRootModels = new ArrayList<ModifiableRootModel>();
for (final ModuleEditor moduleEditor : myModuleEditors.values()) {
final ModifiableRootModel modifiableRootModel = moduleEditor.getModifiableRootModelProxy();
ContainerUtil.addIfNotNull(modifiableRootModels, modifiableRootModel);
}
ModuleDeleteProvider.removeModule(moduleToRemove, null, modifiableRootModels, myModuleModel);
Disposer.dispose(editor);
}
// destroyProcess editor
ModuleDeleteProvider.removeModule(moduleToRemove, null, modifiableRootModels, myModuleModel);
processModuleCountChanged();
Disposer.dispose(selectedEditor);
return true;
}
@@ -49,6 +49,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -344,9 +345,8 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
}
@Override
protected void removeArtifact(Artifact artifact) {
myPackagingEditorContext.getOrCreateModifiableArtifactModel().removeArtifact(artifact);
myContext.getDaemonAnalyzer().removeElement(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
protected List<? extends RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.singletonList(new ArtifactRemoveHandler());
}
@Override
@@ -373,6 +373,21 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
public void dispose() {
}
private class ArtifactRemoveHandler extends RemoveConfigurableHandler<Artifact> {
public ArtifactRemoveHandler() {
super(ArtifactConfigurableBase.class);
}
@Override
public boolean remove(@NotNull Collection<Artifact> artifacts) {
for (Artifact artifact : artifacts) {
myPackagingEditorContext.getOrCreateModifiableArtifactModel().removeArtifact(artifact);
myContext.getDaemonAnalyzer().removeElement(myPackagingEditorContext.getOrCreateArtifactElement(artifact));
}
return true;
}
}
private class AddArtifactAction extends DumbAwareAction {
private final ArtifactType myType;
private final ArtifactTemplate myArtifactTemplate;
@@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
import com.intellij.openapi.roots.libraries.Library;
@@ -38,6 +39,7 @@ import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.ui.NonEmptyInputValidator;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.tree.TreeUtil;
@@ -277,63 +279,95 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
removePaths(pathsToRemove.toArray(new TreePath[pathsToRemove.size()]));
}
@Override
protected boolean removeLibrary(final Library library) {
final LibraryTable table = library.getTable();
if (table != null) {
final LibraryProjectStructureElement libraryElement = new LibraryProjectStructureElement(myContext, library);
final Collection<ProjectStructureElementUsage> usages = new ArrayList<ProjectStructureElementUsage>(myContext.getDaemonAnalyzer().getUsages(libraryElement));
if (usages.size() > 0) {
final MultiMap<String, ProjectStructureElementUsage> containerType2Usage = new MultiMap<String, ProjectStructureElementUsage>();
for (final ProjectStructureElementUsage usage : usages) {
containerType2Usage.putValue(usage.getContainingElement().getTypeName(), usage);
protected List<? extends RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.singletonList(new RemoveConfigurableHandler<Library>(LibraryConfigurable.class) {
@Override
public boolean remove(@NotNull Collection<Library> libraries) {
List<Pair<LibraryProjectStructureElement, Collection<ProjectStructureElementUsage>>> toRemove = new ArrayList<Pair<LibraryProjectStructureElement, Collection<ProjectStructureElementUsage>>>();
String firstLibraryUsageDescription = null;
String firstLibraryWithUsageName = null;
int librariesWithUsages = 0;
for (Library library : libraries) {
final LibraryTable table = library.getTable();
if (table == null) continue;
final LibraryProjectStructureElement libraryElement = new LibraryProjectStructureElement(myContext, library);
final Collection<ProjectStructureElementUsage> usages =
new ArrayList<ProjectStructureElementUsage>(myContext.getDaemonAnalyzer().getUsages(libraryElement));
if (usages.size() > 0) {
if (librariesWithUsages == 0) {
final MultiMap<String, ProjectStructureElementUsage> containerType2Usage = new MultiMap<String, ProjectStructureElementUsage>();
for (final ProjectStructureElementUsage usage : usages) {
containerType2Usage.putValue(usage.getContainingElement().getTypeName(), usage);
}
List<String> types = new ArrayList<String>(containerType2Usage.keySet());
Collections.sort(types);
final StringBuilder sb = new StringBuilder("Library '");
Library libraryModel = myContext.getLibraryModel(library);
sb.append(libraryModel != null ? libraryModel.getName() : library.getName()).append("' is used in ");
for (int i = 0; i < types.size(); i++) {
if (i > 0 && i == types.size() - 1) {
sb.append(" and in ");
}
else if (i > 0) {
sb.append(", in ");
}
String type = types.get(i);
Collection<ProjectStructureElementUsage> usagesOfType = containerType2Usage.get(type);
if (usagesOfType.size() > 1) {
sb.append(usagesOfType.size()).append(" ").append(StringUtil.decapitalize(StringUtil.pluralize(type)));
}
else {
sb.append(StringUtil.decapitalize(usagesOfType.iterator().next().getContainingElement().getPresentableName()));
}
}
firstLibraryWithUsageName = library.getName();
firstLibraryUsageDescription = sb.toString();
}
librariesWithUsages++;
}
toRemove.add(Pair.create(libraryElement, usages));
}
List<String> types = new ArrayList<String>(containerType2Usage.keySet());
Collections.sort(types);
final StringBuilder sb = new StringBuilder("Library '");
Library libraryModel = myContext.getLibraryModel(library);
sb.append(libraryModel != null ? libraryModel.getName() : library.getName()).append("' is used in ");
for (int i = 0; i < types.size(); i++) {
if (i > 0 && i == types.size() - 1) {
sb.append(" and in ");
}
else if (i > 0) {
sb.append(", in ");
}
String type = types.get(i);
Collection<ProjectStructureElementUsage> usagesOfType = containerType2Usage.get(type);
if (usagesOfType.size() > 1) {
sb.append(usagesOfType.size()).append(" ").append(StringUtil.decapitalize(StringUtil.pluralize(type)));
if (librariesWithUsages > 0) {
String message;
if (librariesWithUsages == 1) {
message = firstLibraryUsageDescription + ".\nAre you sure you want to delete this library?";
}
else {
sb.append(StringUtil.decapitalize(usagesOfType.iterator().next().getContainingElement().getPresentableName()));
message = ProjectBundle.message("libraries.remove.confirmation.text", firstLibraryWithUsageName, librariesWithUsages-1);
}
if (Messages.OK != Messages.showOkCancelDialog(myProject, message,
ProjectBundle.message("libraries.remove.confirmation.title", librariesWithUsages), Messages.getQuestionIcon())) {
return false;
}
}
sb.append(".\n\nAre you sure you want to delete this library?");
if (Messages.OK == Messages.showOkCancelDialog(myProject, sb.toString(),
"Delete Library", Messages.getQuestionIcon())) {
for (final ProjectStructureElementUsage usage : usages) {
for (Pair<LibraryProjectStructureElement, Collection<ProjectStructureElementUsage>> pair : toRemove) {
for (ProjectStructureElementUsage usage : pair.getSecond()) {
usage.removeSourceElement();
}
getModelProvider().getModifiableModel().removeLibrary(library);
myContext.getDaemonAnalyzer().removeElement(libraryElement);
return true;
getModelProvider().getModifiableModel().removeLibrary(pair.getFirst().getLibrary());
myContext.getDaemonAnalyzer().removeElement(pair.getFirst());
}
} else {
getModelProvider().getModifiableModel().removeLibrary(library);
myContext.getDaemonAnalyzer().removeElement(libraryElement);
return true;
}
}
return false;
@Override
public boolean canBeRemoved(@NotNull Collection<Library> libraries) {
for (Library library : libraries) {
LibraryTable table = library.getTable();
if (table != null && !table.isEditable()) {
return false;
}
}
return true;
}
});
}
@Override
@@ -22,13 +22,9 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzerListener;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.MasterDetailsComponent;
@@ -39,14 +35,12 @@ import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.navigation.Place;
import com.intellij.util.Function;
import com.intellij.util.IconUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.*;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -323,24 +317,53 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
@Nullable
protected abstract AbstractAddGroup createAddAction();
protected List<? extends RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.emptyList();
}
@NotNull
private MultiMap<RemoveConfigurableHandler, MyNode> groupNodes(List<MyNode> nodes) {
List<? extends RemoveConfigurableHandler<?>> handlers = getRemoveHandlers();
MultiMap<RemoveConfigurableHandler, MyNode> grouped = new LinkedMultiMap<RemoveConfigurableHandler, MyNode>();
for (MyNode node : nodes) {
final NamedConfigurable<?> configurable = node.getConfigurable();
if (configurable == null) continue;
RemoveConfigurableHandler handler = findHandler(handlers, configurable.getClass());
if (handler == null) continue;
grouped.putValue(handler, node);
}
return grouped;
}
private static RemoveConfigurableHandler<?> findHandler(List<? extends RemoveConfigurableHandler<?>> handlers,
Class<? extends NamedConfigurable> configurableClass) {
for (RemoveConfigurableHandler<?> handler : handlers) {
if (handler.getConfigurableClass().isAssignableFrom(configurableClass)) {
return handler;
}
}
return null;
}
protected class MyRemoveAction extends MyDeleteAction {
public MyRemoveAction() {
super(new Condition<Object[]>() {
@Override
public boolean value(final Object[] objects) {
Object[] editableObjects = ContainerUtil.mapNotNull(objects, new Function<Object, Object>() {
@Override
public Object fun(Object object) {
if (object instanceof MyNode) {
final NamedConfigurable namedConfigurable = ((MyNode)object).getConfigurable();
if (namedConfigurable != null) {
return namedConfigurable.getEditableObject();
}
}
return null;
List<MyNode> nodes = new ArrayList<MyNode>();
for (Object object : objects) {
if (!(object instanceof MyNode)) return false;
nodes.add((MyNode)object);
}
MultiMap<RemoveConfigurableHandler, MyNode> map = groupNodes(nodes);
for (Map.Entry<RemoveConfigurableHandler, Collection<MyNode>> entry : map.entrySet()) {
//noinspection unchecked
if (!entry.getKey().canBeRemoved(getEditableObjects(entry.getValue()))) {
return false;
}
}, new Object[0]);
return editableObjects.length == objects.length && canBeRemoved(editableObjects);
}
return true;
}
});
}
@@ -350,77 +373,40 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
final TreePath[] paths = myTree.getSelectionPaths();
if (paths == null) return;
final Set<TreePath> pathsToRemove = new HashSet<TreePath>();
for (TreePath path : paths) {
if (removeFromModel(path)) {
pathsToRemove.add(path);
List<MyNode> removedNodes = removeFromModel(paths);
removeNodes(removedNodes);
}
private List<MyNode> removeFromModel(final TreePath[] paths) {
List<MyNode> nodes = ContainerUtil.mapNotNull(paths, new Function<TreePath, MyNode>() {
@Override
public MyNode fun(TreePath path) {
Object node = path.getLastPathComponent();
return node instanceof MyNode ? (MyNode)node : null;
}
});
MultiMap<RemoveConfigurableHandler, MyNode> grouped = groupNodes(nodes);
List<MyNode> removedNodes = new ArrayList<MyNode>();
for (Map.Entry<RemoveConfigurableHandler, Collection<MyNode>> entry : grouped.entrySet()) {
//noinspection unchecked
boolean removed = entry.getKey().remove(getEditableObjects(entry.getValue()));
if (removed) {
removedNodes.addAll(entry.getValue());
}
}
removePaths(pathsToRemove.toArray(new TreePath[pathsToRemove.size()]));
}
private boolean removeFromModel(final TreePath selectionPath) {
final Object last = selectionPath.getLastPathComponent();
if (!(last instanceof MyNode)) return false;
final MyNode node = (MyNode)last;
final NamedConfigurable configurable = node.getConfigurable();
if (configurable == null) return false;
final Object editableObject = configurable.getEditableObject();
return removeObject(editableObject);
return removedNodes;
}
}
protected boolean canBeRemoved(final Object[] editableObjects) {
for (Object editableObject : editableObjects) {
if (!canObjectBeRemoved(editableObject)) return false;
private static List<?> getEditableObjects(Collection<MyNode> value) {
List<Object> objects = new ArrayList<Object>();
for (MyNode node : value) {
objects.add(node.getConfigurable().getEditableObject());
}
return true;
return objects;
}
private static boolean canObjectBeRemoved(Object editableObject) {
if (editableObject instanceof Sdk ||
editableObject instanceof Module ||
editableObject instanceof Facet ||
editableObject instanceof Artifact) {
return true;
}
if (editableObject instanceof Library) {
final LibraryTable table = ((Library)editableObject).getTable();
return table == null || table.isEditable();
}
return false;
}
protected boolean removeObject(final Object editableObject) {
// todo keep only removeModule() and removeFacet() here because other removeXXX() are empty here and overridden in subclasses? Override removeObject() instead?
if (editableObject instanceof Sdk) {
removeJdk((Sdk)editableObject);
}
else if (editableObject instanceof Module) {
if (!removeModule((Module)editableObject)) return false;
}
else if (editableObject instanceof Facet) {
if (removeFacet((Facet)editableObject).isEmpty()) return false;
}
else if (editableObject instanceof Library) {
if (!removeLibrary((Library)editableObject)) return false;
}
else if (editableObject instanceof Artifact) {
removeArtifact((Artifact)editableObject);
}
return true;
}
protected void removeArtifact(Artifact artifact) {
}
protected boolean removeLibrary(Library library) {
return false;
}
protected void removeFacetNodes(@NotNull List<Facet> facets) {
for (Facet facet : facets) {
@@ -431,17 +417,6 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
}
}
protected List<Facet> removeFacet(final Facet facet) {
return myContext.myModulesConfigurator.getFacetsConfigurator().removeFacet(facet);
}
protected boolean removeModule(final Module module) {
return true;
}
protected void removeJdk(final Sdk editableObject) {
}
protected abstract static class AbstractAddGroup extends ActionGroup implements ActionGroupWithPreselection {
protected AbstractAddGroup(String text, Icon icon) {
@@ -283,16 +283,6 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
return actions;
}
@Override
protected List<Facet> removeFacet(final Facet facet) {
List<Facet> removed = super.removeFacet(facet);
ModuleStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
for (Facet removedFacet : removed) {
myContext.getDaemonAnalyzer().removeElement(new FacetProjectStructureElement(myContext, removedFacet));
}
return removed;
}
@Override
protected boolean updateMultiSelection(final List<NamedConfigurable> selectedConfigurables) {
return updateMultiSelection(selectedConfigurables, getDetailsComponent());
@@ -352,6 +342,11 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
return null;
}
@Override
protected List<? extends RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.singletonList(new FacetRemoveHandler());
}
@Override
protected void processRemovedItems() {
}
@@ -407,6 +402,24 @@ public class FacetStructureConfigurable extends BaseStructureConfigurable {
public void dispose() {
}
private class FacetRemoveHandler extends RemoveConfigurableHandler<Facet> {
public FacetRemoveHandler() {
super(FacetConfigurable.class);
}
@Override
public boolean remove(@NotNull Collection<Facet> facets) {
for (Facet facet : facets) {
List<Facet> removed = myContext.myModulesConfigurator.getFacetsConfigurator().removeFacet(facet);
ModuleStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
for (Facet removedFacet : removed) {
myContext.getDaemonAnalyzer().removeElement(new FacetProjectStructureElement(myContext, removedFacet));
}
}
return true;
}
}
private class FacetConfigurableNode extends MyNode {
public FacetConfigurableNode(final FacetConfigurable facetConfigurable) {
super(facetConfigurable);
@@ -38,10 +38,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.TreePath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.*;
public class JdkListConfigurable extends BaseStructureConfigurable {
private final ProjectSdksModel myJdksTreeModel;
@@ -212,9 +209,8 @@ public class JdkListConfigurable extends BaseStructureConfigurable {
}
@Override
protected void removeJdk(final Sdk jdk) {
myJdksTreeModel.removeSdk(jdk);
myContext.getDaemonAnalyzer().removeElement(new SdkProjectStructureElement(myContext, jdk));
protected List<? extends RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.singletonList(new SdkRemoveHandler());
}
@Override
@@ -223,4 +219,19 @@ public class JdkListConfigurable extends BaseStructureConfigurable {
String getEmptySelectionString() {
return "Select an SDK to view or edit its details here";
}
private class SdkRemoveHandler extends RemoveConfigurableHandler<Sdk> {
public SdkRemoveHandler() {
super(JdkConfigurable.class);
}
@Override
public boolean remove(@NotNull Collection<Sdk> sdks) {
for (Sdk sdk : sdks) {
myJdksTreeModel.removeSdk(sdk);
myContext.getDaemonAnalyzer().removeElement(new SdkProjectStructureElement(myContext, sdk));
}
return true;
}
}
}
@@ -113,10 +113,17 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
private final FacetEditorFacadeImpl myFacetEditorFacade = new FacetEditorFacadeImpl(this, TREE_UPDATER);
private final List<RemoveConfigurableHandler<?>> myRemoveHandlers;
public ModuleStructureConfigurable(Project project, ModuleManager manager) {
super(project);
myModuleManager = manager;
myRemoveHandlers = new ArrayList<RemoveConfigurableHandler<?>>();
myRemoveHandlers.add(new ModuleRemoveHandler());
myRemoveHandlers.add(new FacetInModuleRemoveHandler());
for (ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
myRemoveHandlers.addAll(extension.getRemoveHandlers());
}
}
@Override
@@ -639,30 +646,6 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
PlatformIcons.CLOSED_MODULE_GROUP_ICON);
}
@Override
protected boolean canBeRemoved(final Object[] editableObjects) {
if (super.canBeRemoved(editableObjects)) {
return true;
}
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
if (extension.canBeRemoved(editableObjects)) {
return true;
}
}
return false;
}
@Override
protected boolean removeObject(final Object editableObject) {
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
if (extension.removeObject(editableObject)) {
return true;
}
}
return super.removeObject(editableObject);
}
private boolean canBeCopiedByExtension(final NamedConfigurable configurable) {
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
if (extension.canBeCopied(configurable)) {
@@ -678,6 +661,46 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
}
}
private class FacetInModuleRemoveHandler extends RemoveConfigurableHandler<Facet> {
public FacetInModuleRemoveHandler() {
super(FacetConfigurable.class);
}
@Override
public boolean remove(@NotNull Collection<Facet> facets) {
for (Facet facet : facets) {
List<Facet> removed = myContext.myModulesConfigurator.getFacetsConfigurator().removeFacet(facet);
FacetStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
}
return true;
}
}
private class ModuleRemoveHandler extends RemoveConfigurableHandler<Module> {
public ModuleRemoveHandler() {
super(ModuleConfigurable.class);
}
@Override
public boolean remove(@NotNull Collection<Module> modules) {
ModulesConfigurator modulesConfigurator = myContext.myModulesConfigurator;
List<Module> deleted = modulesConfigurator.deleteModules(modules);
if (deleted.isEmpty()) {
return false;
}
for (Module module : deleted) {
List<Facet> removed = modulesConfigurator.getFacetsConfigurator().removeAllFacets(module);
FacetStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
myContext.getDaemonAnalyzer().removeElement(new ModuleProjectStructureElement(myContext, module));
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
extension.moduleRemoved(module);
}
}
return true;
}
}
private class MyDataProviderWrapper extends JPanel implements DataProvider {
public MyDataProviderWrapper(final JComponent component) {
super(new BorderLayout());
@@ -826,27 +849,8 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
}
@Override
protected List<Facet> removeFacet(final Facet facet) {
List<Facet> removed = super.removeFacet(facet);
FacetStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
return removed;
}
@Override
protected boolean removeModule(final Module module) {
ModulesConfigurator modulesConfigurator = myContext.myModulesConfigurator;
if (!modulesConfigurator.deleteModule(module)) {
//wait for confirmation
return false;
}
List<Facet> removed = modulesConfigurator.getFacetsConfigurator().removeAllFacets(module);
FacetStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
myContext.getDaemonAnalyzer().removeElement(new ModuleProjectStructureElement(myContext, module));
for (final ModuleStructureExtension extension : ModuleStructureExtension.EP_NAME.getExtensions()) {
extension.moduleRemoved(module);
}
return true;
protected List<RemoveConfigurableHandler<?>> getRemoveHandlers() {
return myRemoveHandlers;
}
@Override
@@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public abstract class ModuleStructureExtension {
@@ -45,12 +46,8 @@ public abstract class ModuleStructureExtension {
public void disposeUIResources() {
}
public boolean canBeRemoved(final Object[] editableObjects) {
return false;
}
public boolean removeObject(final Object editableObject) {
return false;
public List<RemoveConfigurableHandler<?>> getRemoveHandlers() {
return Collections.emptyList();
}
public Collection<AnAction> createAddActions(final NullableComputable<MasterDetailsComponent.MyNode> selectedNodeRetriever,
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.roots.ui.configuration.projectRoot;
import com.intellij.openapi.ui.NamedConfigurable;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author nik
*/
public abstract class RemoveConfigurableHandler<T> {
private final Class<? extends NamedConfigurable<T>> myConfigurableClass;
public RemoveConfigurableHandler(Class<? extends NamedConfigurable<T>> configurableClass) {
myConfigurableClass = configurableClass;
}
public Class<? extends NamedConfigurable<T>> getConfigurableClass() {
return myConfigurableClass;
}
public boolean canBeRemoved(@NotNull Collection<T> objects) {
return true;
}
public abstract boolean remove(@NotNull Collection<T> objects);
}
@@ -789,10 +789,17 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
}
protected void removePaths(final TreePath... paths) {
List<MyNode> nodes = new ArrayList<MyNode>();
for (TreePath path : paths) {
nodes.add((MyNode)path.getLastPathComponent());
}
removeNodes(nodes);
}
protected void removeNodes(final List<MyNode> nodes) {
MyNode parentNode = null;
int idx = -1;
for (TreePath path : paths) {
final MyNode node = (MyNode)path.getLastPathComponent();
for (MyNode node : nodes) {
final NamedConfigurable namedConfigurable = node.getConfigurable();
final Object editableObject = namedConfigurable.getEditableObject();
parentNode = (MyNode)node.getParent();
@@ -804,7 +811,7 @@ public abstract class MasterDetailsComponent implements Configurable, DetailsCom
namedConfigurable.disposeUIResources();
}
if (paths.length > 0) {
if (!nodes.isEmpty()) {
if (parentNode != null && idx != -1) {
DefaultMutableTreeNode toSelect = null;
if (idx < parentNode.getChildCount()) {
@@ -144,9 +144,9 @@ module.add.error.message=Error adding module to project: {0}
module.add.error.title=Add Module
module.add.action=Add
module.remove.action=Remove
module.remove.last.confirmation=Are you sure you want to remove the only module from this project?\nNo files will be deleted on disk.
module.remove.confirmation=Remove module ''{0}'' from the project?\nNo files will be deleted on disk.
module.remove.confirmation.title=Remove Module
module.remove.last.confirmation=Are you sure you want to remove {0, choice, 1#the only module|2#all modules} from this project?\nNo files will be deleted on disk.
module.remove.confirmation=Remove {1, choice, 1#module ''''{0}''''|2#{1} modules} from the project?\nNo files will be deleted on disk.
module.remove.confirmation.title=Remove {0, choice, 1#Module|2#Modules}
module.classpath.button.edit=Ed&it...
module.libraries.include.all.button=Include All
module.libraries.exclude.all.button=Exclude All
@@ -244,6 +244,9 @@ libraries.node.text.module=Libraries contain classes that add up various functio
Expand the node and select child items to manage Module libraries.<br><br> \
\
To attach a library to a module, select that module, click the Dependencies tab, click Add and specify the library location.
libraries.remove.confirmation.title=Remove {0, choice, 1#Library|2#Libraries}
libraries.remove.confirmation.text=Library ''{0}'' and {1} more {1, choice, 1#library|2#libraries} are used in the project.\n \
Are you sure you want to delete all selected libraries?
jdks.node.display.name=SDKs
project.language.level.combo.item=Project default
add.action.name=Add new ...