mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
show only one confirmation dialog when deleting libraries or modules from Project Structure (IDEA-83808)
This commit is contained in:
+33
-23
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+18
-3
@@ -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;
|
||||
|
||||
+78
-44
@@ -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
|
||||
|
||||
+68
-93
@@ -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) {
|
||||
|
||||
+23
-10
@@ -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);
|
||||
|
||||
+18
-7
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-45
@@ -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
|
||||
|
||||
+3
-6
@@ -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,
|
||||
|
||||
+42
@@ -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 ...
|
||||
|
||||
Reference in New Issue
Block a user