mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
find usages & validation in project structure reworked
This commit is contained in:
@@ -45,7 +45,7 @@ public interface ArtifactEditorContext extends PackagingElementResolvingContext
|
||||
|
||||
CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact);
|
||||
|
||||
void ensureRootIsWritable(@NotNull Artifact artifact);
|
||||
void editLayout(@NotNull Artifact artifact, Runnable runnable);
|
||||
|
||||
ArtifactEditor getOrCreateEditor(Artifact originalArtifact);
|
||||
|
||||
|
||||
@@ -38,6 +38,10 @@ import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableEdi
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.util.CellAppearance;
|
||||
import com.intellij.openapi.roots.ui.util.OrderEntryCellAppearanceUtils;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -330,12 +334,13 @@ public class ClasspathPanel extends JPanel {
|
||||
if (orderEntry == null) {
|
||||
continue;
|
||||
}
|
||||
ModuleStructureConfigurable.getInstance(myProject).getContext().clearCaches(orderEntry);
|
||||
myRootModel.removeOrderEntry(orderEntry);
|
||||
}
|
||||
final int[] selectedRows = myEntryTable.getSelectedRows();
|
||||
myModel.fireTableDataChanged();
|
||||
TableUtil.selectRows(myEntryTable, selectedRows);
|
||||
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(myProject).getContext();
|
||||
context.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(context, myRootModel.getModule()));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -480,7 +485,6 @@ public class ClasspathPanel extends JPanel {
|
||||
final TableItem tableItem = createTableItem(item);
|
||||
if ( tableItem != null ) {
|
||||
myModel.addItem(tableItem);
|
||||
rootConfigurable.getContext().clearCaches(tableItem.getEntry());
|
||||
}
|
||||
}
|
||||
myModel.fireTableDataChanged();
|
||||
@@ -489,6 +493,8 @@ public class ClasspathPanel extends JPanel {
|
||||
selectionModel.setSelectionInterval(myModel.getRowCount() - chosen.size(), myModel.getRowCount() - 1);
|
||||
TableUtil.scrollSelectionToVisible(myEntryTable);
|
||||
|
||||
final StructureConfigurableContext context = rootConfigurable.getContext();
|
||||
context.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(context, myRootModel.getModule()));
|
||||
}
|
||||
finally {
|
||||
if (dialog instanceof ChooseNamedLibraryAction.MyChooserDialog) {
|
||||
@@ -1151,7 +1157,6 @@ public class ClasspathPanel extends JPanel {
|
||||
chosen.removeAll(getAlreadyAddedLibraries());
|
||||
final Module module = myRootModel.getModule();
|
||||
final Project project = module.getProject();
|
||||
ModuleStructureConfigurable.getInstance(project).getContext().clearCaches(module, chosen);
|
||||
return chosen;
|
||||
}
|
||||
|
||||
@@ -1175,29 +1180,38 @@ public class ClasspathPanel extends JPanel {
|
||||
}
|
||||
|
||||
protected boolean isEnabled() {
|
||||
return getSelectedObject() != null;
|
||||
return getSelectedElement() != null;
|
||||
}
|
||||
|
||||
protected Object getSelectedObject() {
|
||||
protected ProjectStructureElement getSelectedElement() {
|
||||
int row = myEntryTable.getSelectedRow();
|
||||
if (0 <= row && row < myModel.getRowCount()) {
|
||||
TableItem item = myModel.getItemAt(row);
|
||||
if (item instanceof LibItem) {
|
||||
LibraryOrderEntry orderEntry = ((LibItem)item).getEntry();
|
||||
if (orderEntry != null) {
|
||||
return orderEntry.getLibrary();
|
||||
final Library library = orderEntry.getLibrary();
|
||||
if (library != null) {
|
||||
return new LibraryProjectStructureElement(getContext(), library);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item instanceof ModuleItem) {
|
||||
ModuleOrderEntry orderEntry = ((ModuleItem)item).getEntry();
|
||||
if (orderEntry != null) {
|
||||
return orderEntry.getModule();
|
||||
final Module module = orderEntry.getModule();
|
||||
if (module != null) {
|
||||
return new ModuleProjectStructureElement(getContext(), module);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (item instanceof JdkItem) {
|
||||
JdkOrderEntry orderEntry = ((JdkItem)item).getEntry();
|
||||
if (orderEntry != null) {
|
||||
return orderEntry.getJdk();
|
||||
final Sdk jdk = orderEntry.getJdk();
|
||||
if (jdk != null) {
|
||||
return new SdkProjectStructureElement(getContext(), jdk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-1
@@ -25,6 +25,8 @@ import com.intellij.openapi.projectRoots.SdkModel;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectJdksModel;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
@@ -155,7 +157,8 @@ public class ModuleJdkConfigurable implements Disposable {
|
||||
private void clearCaches(final Sdk oldJdk, final Sdk selectedModuleJdk) {
|
||||
final Module module = myRootModel.getModule();
|
||||
final Project project = module.getProject();
|
||||
ModuleStructureConfigurable.getInstance(project).getContext().clearCaches(module, oldJdk, selectedModuleJdk);
|
||||
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(project).getContext();
|
||||
context.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(context, module));
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
|
||||
+2
-1
@@ -40,6 +40,7 @@ import com.intellij.openapi.roots.ui.configuration.actions.ModuleDeleteProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectJdksModel;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
@@ -487,7 +488,7 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change
|
||||
if (module == moduleEditor.getModule() && Comparing.strEqual(moduleEditor.getName(), oldName)) {
|
||||
moduleEditor.setModuleName(name);
|
||||
moduleEditor.updateCompilerOutputPathChanged(ProjectStructureConfigurable.getInstance(myProject).getProjectConfig().getCompilerOutputUrl(), name);
|
||||
myContext.invalidateModuleName(moduleEditor.getModule());
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(myContext, module), true, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -26,6 +26,8 @@ import com.intellij.openapi.projectRoots.SdkModel;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectJdksModel;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -91,7 +93,7 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable {
|
||||
myCbProjectJdk.setSelectedJdk(jdk);
|
||||
} else {
|
||||
myCbProjectJdk.setInvalidJdk(sdkName);
|
||||
clearCaches(null);
|
||||
clearCaches();
|
||||
}
|
||||
} else {
|
||||
myCbProjectJdk.setSelectedJdk(null);
|
||||
@@ -108,7 +110,7 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable {
|
||||
if (myFreeze) return;
|
||||
final Sdk oldJdk = myJdksModel.getProjectJdk();
|
||||
myJdksModel.setProjectJdk(myCbProjectJdk.getSelectedJdk());
|
||||
clearCaches(oldJdk);
|
||||
clearCaches();
|
||||
}
|
||||
});
|
||||
myJdkPanel.add(new JLabel(ProjectBundle.message("module.libraries.target.jdk.project.radio")), new GridBagConstraints(0, 0, 3, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(0, 0, 4, 0), 0, 0));
|
||||
@@ -123,11 +125,12 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable {
|
||||
});
|
||||
}
|
||||
|
||||
private void clearCaches(final Sdk oldJdk) {
|
||||
private void clearCaches() {
|
||||
final ModuleStructureConfigurable rootConfigurable = ModuleStructureConfigurable.getInstance(myProject);
|
||||
Module[] modules = rootConfigurable.getModules();
|
||||
for (Module module : modules) {
|
||||
rootConfigurable.getContext().clearCaches(module, oldJdk, getSelectedProjectJdk());
|
||||
final StructureConfigurableContext context = rootConfigurable.getContext();
|
||||
context.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(context, module));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -89,7 +89,7 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent implements C
|
||||
myRoot.removeAllChildren();
|
||||
final HashMap<Sdk, Sdk> sdks = myProjectJdksModel.getProjectJdks();
|
||||
for (Sdk sdk : sdks.keySet()) {
|
||||
final JdkConfigurable configurable = new JdkConfigurable((ProjectJdkImpl)sdks.get(sdk), myProjectJdksModel, TREE_UPDATER, myHistory);
|
||||
final JdkConfigurable configurable = new JdkConfigurable((ProjectJdkImpl)sdks.get(sdk), myProjectJdksModel, TREE_UPDATER, myHistory, myProject);
|
||||
addNode(new MyNode(configurable), myRoot);
|
||||
}
|
||||
selectJdk(myProjectJdksModel.getProjectJdk()); //restore selection
|
||||
@@ -153,7 +153,7 @@ public class ProjectJdksConfigurable extends MasterDetailsComponent implements C
|
||||
group.getTemplatePresentation().setIcon(Icons.ADD_ICON);
|
||||
myProjectJdksModel.createAddActions(group, myTree, new Consumer<Sdk>() {
|
||||
public void consume(final Sdk projectJdk) {
|
||||
addNode(new MyNode(new JdkConfigurable(((ProjectJdkImpl)projectJdk), myProjectJdksModel, TREE_UPDATER, myHistory), false), myRoot);
|
||||
addNode(new MyNode(new JdkConfigurable(((ProjectJdkImpl)projectJdk), myProjectJdksModel, TREE_UPDATER, myHistory, myProject), false), myRoot);
|
||||
selectNodeInTree(findNodeByObject(myRoot, projectJdk));
|
||||
}
|
||||
});
|
||||
|
||||
+12
-14
@@ -111,12 +111,13 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
|
||||
myArtifactsStructureConfigurable = artifactsStructureConfigurable;
|
||||
|
||||
myModuleConfigurator = new ModulesConfigurator(myProject, myProjectJdksModel);
|
||||
myContext = new StructureConfigurableContext(myProject, myModuleManager, myModuleConfigurator);
|
||||
myContext = new StructureConfigurableContext(myProject, myModuleConfigurator);
|
||||
myModuleConfigurator.setContext(myContext);
|
||||
|
||||
myProjectLibrariesConfig = projectLibrariesConfigurable;
|
||||
myGlobalLibrariesConfig = globalLibrariesConfigurable;
|
||||
myModulesConfig = moduleStructureConfigurable;
|
||||
|
||||
myProjectLibrariesConfig.init(myContext);
|
||||
myGlobalLibrariesConfig.init(myContext);
|
||||
myModulesConfig.init(myContext);
|
||||
@@ -226,8 +227,10 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
|
||||
}
|
||||
|
||||
private void addJdkListConfig() {
|
||||
myJdkListConfig = JdkListConfigurable.getInstance(myProject);
|
||||
myJdkListConfig.init(myContext);
|
||||
if (myJdkListConfig == null) {
|
||||
myJdkListConfig = JdkListConfigurable.getInstance(myProject);
|
||||
myJdkListConfig.init(myContext);
|
||||
}
|
||||
addConfigurable(myJdkListConfig);
|
||||
}
|
||||
|
||||
@@ -265,18 +268,13 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
|
||||
}
|
||||
|
||||
//cleanup
|
||||
myContext.myUpdateDependenciesAlarm.cancelAllRequests();
|
||||
myContext.myUpdateDependenciesAlarm.addRequest(new Runnable(){
|
||||
myContext.getDaemonAnalyzer().clearCaches();
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run() {
|
||||
if (myWasUiDisposed) return;
|
||||
reset();
|
||||
}
|
||||
});
|
||||
if (myWasUiDisposed) return;
|
||||
reset();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@@ -323,7 +321,7 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se
|
||||
|
||||
myUiState.proportion = mySplitter.getProportion();
|
||||
saveSideProportion();
|
||||
|
||||
myContext.getDaemonAnalyzer().stop();
|
||||
for (Configurable each : myName2Config) {
|
||||
each.disposeUIResources();
|
||||
}
|
||||
|
||||
+13
-3
@@ -17,8 +17,10 @@ package com.intellij.openapi.roots.ui.configuration.artifacts;
|
||||
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectStructureElementConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
@@ -34,17 +36,20 @@ import java.awt.event.ActionListener;
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactConfigurable extends NamedConfigurable<Artifact> {
|
||||
public class ArtifactConfigurable extends ProjectStructureElementConfigurable<Artifact> {
|
||||
private final Artifact myOriginalArtifact;
|
||||
private final ArtifactsStructureConfigurableContext myArtifactsStructureContext;
|
||||
private final ArtifactEditorImpl myEditor;
|
||||
private boolean myIsInUpdateName;
|
||||
private ProjectStructureElement myProjectStructureElement;
|
||||
|
||||
public ArtifactConfigurable(Artifact originalArtifact, ArtifactsStructureConfigurableContextImpl artifactsStructureContext, final Runnable updateTree) {
|
||||
public ArtifactConfigurable(Artifact originalArtifact, ArtifactsStructureConfigurableContextImpl artifactsStructureContext, final Runnable updateTree,
|
||||
StructureConfigurableContext context) {
|
||||
super(true, updateTree);
|
||||
myOriginalArtifact = originalArtifact;
|
||||
myArtifactsStructureContext = artifactsStructureContext;
|
||||
myEditor = artifactsStructureContext.getOrCreateEditor(originalArtifact);
|
||||
myProjectStructureElement = new ArtifactProjectStructureElement(context, myArtifactsStructureContext, myOriginalArtifact);
|
||||
}
|
||||
|
||||
public void setDisplayName(String name) {
|
||||
@@ -55,6 +60,11 @@ public class ArtifactConfigurable extends NamedConfigurable<Artifact> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getProjectStructureElement() {
|
||||
return myProjectStructureElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateName() {
|
||||
myIsInUpdateName = true;
|
||||
|
||||
+33
-8
@@ -15,14 +15,21 @@
|
||||
*/
|
||||
package com.intellij.openapi.roots.ui.configuration.artifacts;
|
||||
|
||||
import com.intellij.facet.Facet;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.impl.ModuleLibraryOrderEntryImpl;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.packaging.ChooseLibrariesDialog;
|
||||
import com.intellij.openapi.roots.ui.configuration.libraryEditor.ChooseModulesDialog;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.ui.configuration.packaging.ChooseLibrariesDialog;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.artifacts.ArtifactModel;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
@@ -31,11 +38,10 @@ import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.ui.ArtifactEditor;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import com.intellij.packaging.ui.ManifestFileConfiguration;
|
||||
import com.intellij.facet.Facet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -69,8 +75,8 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
|
||||
return myParent.getRootElement(artifact);
|
||||
}
|
||||
|
||||
public void ensureRootIsWritable(@NotNull Artifact artifact) {
|
||||
myParent.ensureRootIsWritable(artifact);
|
||||
public void editLayout(@NotNull Artifact artifact, Runnable runnable) {
|
||||
myParent.editLayout(artifact, runnable);
|
||||
}
|
||||
|
||||
public ArtifactEditor getOrCreateEditor(Artifact artifact) {
|
||||
@@ -90,7 +96,26 @@ public class ArtifactEditorContextImpl implements ArtifactEditorContext {
|
||||
}
|
||||
|
||||
public void selectLibrary(@NotNull Library library) {
|
||||
ProjectStructureConfigurable.getInstance(getProject()).selectProjectOrGlobalLibrary(library, true);
|
||||
final LibraryTable table = library.getTable();
|
||||
if (table != null) {
|
||||
ProjectStructureConfigurable.getInstance(getProject()).selectProjectOrGlobalLibrary(library, true);
|
||||
}
|
||||
else {
|
||||
final Module module = ((LibraryImpl)library).getModule();
|
||||
if (module != null) {
|
||||
final ModuleRootModel rootModel = myParent.getModulesProvider().getRootModel(module);
|
||||
final String libraryName = library.getName();
|
||||
for (OrderEntry entry : rootModel.getOrderEntries()) {
|
||||
if (entry instanceof ModuleLibraryOrderEntryImpl) {
|
||||
final ModuleLibraryOrderEntryImpl libraryEntry = (ModuleLibraryOrderEntryImpl)entry;
|
||||
if (libraryName.equals(libraryEntry.getLibraryName())) {
|
||||
ModuleStructureConfigurable.getInstance(getProject()).selectOrderEntry(module, libraryEntry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Artifact> chooseArtifacts(final List<? extends Artifact> artifacts, final String title) {
|
||||
|
||||
+6
-3
@@ -339,7 +339,7 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
|
||||
return myLayoutTreeComponent;
|
||||
}
|
||||
|
||||
public void updateOutputPath(@NotNull String oldArtifactName, @NotNull String newArtifactName) {
|
||||
public void updateOutputPath(@NotNull String oldArtifactName, @NotNull final String newArtifactName) {
|
||||
final String oldDefaultPath = ArtifactUtil.getDefaultArtifactOutputPath(oldArtifactName, myProject);
|
||||
if (Comparing.equal(oldDefaultPath, getConfiguredOutputPath())) {
|
||||
setOutputPath(ArtifactUtil.getDefaultArtifactOutputPath(newArtifactName, myProject));
|
||||
@@ -349,8 +349,11 @@ public class ArtifactEditorImpl implements ArtifactEditorEx {
|
||||
final String fileName = FileUtil.getNameWithoutExtension(name);
|
||||
final String extension = FileUtil.getExtension(name);
|
||||
if (fileName.equals(oldArtifactName) && extension.length() > 0) {
|
||||
myLayoutTreeComponent.ensureRootIsWritable();
|
||||
((ArchivePackagingElement)getRootElement()).setArchiveFileName(newArtifactName + "." + extension);
|
||||
myLayoutTreeComponent.editLayout(new Runnable() {
|
||||
public void run() {
|
||||
((ArchivePackagingElement)getRootElement()).setArchiveFileName(newArtifactName + "." + extension);
|
||||
}
|
||||
});
|
||||
myLayoutTreeComponent.updateTreeNodesPresentation();
|
||||
}
|
||||
}
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.artifacts;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElement;
|
||||
import com.intellij.packaging.impl.artifacts.ArtifactUtil;
|
||||
import com.intellij.packaging.impl.artifacts.PackagingElementProcessor;
|
||||
import com.intellij.packaging.impl.elements.LibraryPackagingElement;
|
||||
import com.intellij.packaging.impl.elements.ModuleOutputPackagingElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactProjectStructureElement extends ProjectStructureElement {
|
||||
private final ArtifactsStructureConfigurableContext myArtifactsStructureContext;
|
||||
private final Artifact myOriginalArtifact;
|
||||
|
||||
public ArtifactProjectStructureElement(StructureConfigurableContext context,
|
||||
ArtifactsStructureConfigurableContext artifactsStructureContext, Artifact originalArtifact) {
|
||||
super(context);
|
||||
myArtifactsStructureContext = artifactsStructureContext;
|
||||
myOriginalArtifact = originalArtifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(ProjectStructureProblemsHolder problemsHolder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProjectStructureElementUsage> getUsagesInElement() {
|
||||
final Artifact artifact = myArtifactsStructureContext.getArtifactModel().getArtifactByOriginal(myOriginalArtifact);
|
||||
final List<ProjectStructureElementUsage> usages = new ArrayList<ProjectStructureElementUsage>();
|
||||
ArtifactUtil.processPackagingElements(myArtifactsStructureContext.getRootElement(artifact), null, new PackagingElementProcessor<PackagingElement<?>>() {
|
||||
@Override
|
||||
public boolean process(@NotNull List<CompositePackagingElement<?>> parents, @NotNull PackagingElement<?> packagingElement) {
|
||||
if (packagingElement instanceof ModuleOutputPackagingElement) {
|
||||
final Module module = ((ModuleOutputPackagingElement)packagingElement).findModule(myArtifactsStructureContext);
|
||||
if (module != null) {
|
||||
usages.add(new UsageInArtifact(myOriginalArtifact, myArtifactsStructureContext, new ModuleProjectStructureElement(myContext, module),
|
||||
ArtifactProjectStructureElement.this, getPathFromRoot(parents, "/"), packagingElement));
|
||||
}
|
||||
}
|
||||
else if (packagingElement instanceof LibraryPackagingElement) {
|
||||
final Library library = ((LibraryPackagingElement)packagingElement).findLibrary(myArtifactsStructureContext);
|
||||
if (library != null) {
|
||||
usages.add(new UsageInArtifact(myOriginalArtifact, myArtifactsStructureContext, new LibraryProjectStructureElement(myContext, library),
|
||||
ArtifactProjectStructureElement.this, getPathFromRoot(parents, "/"), packagingElement));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, myArtifactsStructureContext, false, artifact.getArtifactType());
|
||||
return usages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "artifact:" + myOriginalArtifact.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ArtifactProjectStructureElement)) return false;
|
||||
|
||||
return myOriginalArtifact.equals(((ArtifactProjectStructureElement)o).myOriginalArtifact);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myOriginalArtifact.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean highlightIfUnused() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+17
-1
@@ -27,6 +27,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.BaseStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.packaging.artifacts.*;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -34,6 +35,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -58,6 +62,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
|
||||
public void artifactAdded(@NotNull Artifact artifact) {
|
||||
final MyNode node = addArtifactNode(artifact);
|
||||
selectNodeInTree(node);
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -75,8 +80,18 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
|
||||
final List<ProjectStructureElement> elements = new ArrayList<ProjectStructureElement>();
|
||||
for (Artifact artifact : myPackagingEditorContext.getArtifactModel().getArtifacts()) {
|
||||
elements.add(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
private MyNode addArtifactNode(final Artifact artifact) {
|
||||
final MyNode node = new MyNode(new ArtifactConfigurable(artifact, myPackagingEditorContext, TREE_UPDATER));
|
||||
final MyNode node = new MyNode(new ArtifactConfigurable(artifact, myPackagingEditorContext, TREE_UPDATER, myContext));
|
||||
addNode(node, myRoot);
|
||||
return node;
|
||||
}
|
||||
@@ -160,6 +175,7 @@ public class ArtifactsStructureConfigurable extends BaseStructureConfigurable {
|
||||
@Override
|
||||
protected void removeArtifact(Artifact artifact) {
|
||||
myPackagingEditorContext.getModifiableArtifactModel().removeArtifact(artifact);
|
||||
myContext.getDaemonAnalyzer().removeElement(new ArtifactProjectStructureElement(myContext, myPackagingEditorContext, artifact));
|
||||
}
|
||||
|
||||
protected void processRemovedItems() {
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ public interface ArtifactsStructureConfigurableContext extends PackagingElementR
|
||||
|
||||
CompositePackagingElement<?> getRootElement(@NotNull Artifact artifact);
|
||||
|
||||
void ensureRootIsWritable(@NotNull Artifact artifact);
|
||||
void editLayout(@NotNull Artifact artifact, Runnable action);
|
||||
|
||||
ArtifactEditor getOrCreateEditor(Artifact artifact);
|
||||
}
|
||||
|
||||
+3
-2
@@ -86,13 +86,14 @@ class ArtifactsStructureConfigurableContextImpl implements ArtifactsStructureCon
|
||||
return root;
|
||||
}
|
||||
|
||||
public void ensureRootIsWritable(@NotNull Artifact artifact) {
|
||||
public void editLayout(@NotNull Artifact artifact, Runnable action) {
|
||||
artifact = getOriginalArtifact(artifact);
|
||||
final ModifiableArtifact modifiableArtifact = getModifiableArtifactModel().getOrCreateModifiableArtifact(artifact);
|
||||
if (modifiableArtifact.getRootElement() == artifact.getRootElement()) {
|
||||
modifiableArtifact.setRootElement(getRootElement(artifact));
|
||||
}
|
||||
|
||||
action.run();
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new ArtifactProjectStructureElement(myContext, this, artifact));
|
||||
}
|
||||
|
||||
public ArtifactEditorImpl getOrCreateEditor(Artifact artifact) {
|
||||
|
||||
+21
-1
@@ -23,8 +23,10 @@ import com.intellij.ide.dnd.aware.DnDAwareTree;
|
||||
import com.intellij.ide.util.treeView.AbstractTreeBuilder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.CompositePackagingElementNode;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingElementNode;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.packaging.elements.PackagingElement;
|
||||
import com.intellij.packaging.elements.RenameablePackagingElement;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
@@ -156,6 +158,19 @@ public class LayoutTree extends SimpleDnDAwareTree implements AdvancedDnDSource
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PackagingElementNode<?> findCompositeNodeByPath(String parentPath) {
|
||||
PackagingElementNode<?> node = getRootPackagingNode();
|
||||
for (String name : StringUtil.split(parentPath, "/")) {
|
||||
final CompositePackagingElementNode child = node.findCompositeChild(name);
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
private class LayoutTreeCellEditor extends DefaultCellEditor {
|
||||
public LayoutTreeCellEditor() {
|
||||
super(new JTextField());
|
||||
@@ -189,7 +204,12 @@ public class LayoutTree extends SimpleDnDAwareTree implements AdvancedDnDSource
|
||||
}
|
||||
final boolean stopped = super.stopCellEditing();
|
||||
if (stopped && currentElement != null) {
|
||||
currentElement.rename(newValue);
|
||||
final RenameablePackagingElement finalCurrentElement = currentElement;
|
||||
myArtifactsEditor.getLayoutTreeComponent().editLayout(new Runnable() {
|
||||
public void run() {
|
||||
finalCurrentElement.rename(newValue);
|
||||
}
|
||||
});
|
||||
myArtifactsEditor.queueValidation();
|
||||
myArtifactsEditor.getLayoutTreeComponent().updatePropertiesPanel(true);
|
||||
addSubtreeToUpdate((DefaultMutableTreeNode)path.getLastPathComponent());
|
||||
|
||||
+65
-34
@@ -19,10 +19,7 @@ import com.intellij.ide.dnd.DnDEvent;
|
||||
import com.intellij.ide.dnd.DnDManager;
|
||||
import com.intellij.ide.dnd.DnDTarget;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingElementNode;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingNodeSource;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingTreeNodeFactory;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.ArtifactRootNode;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.*;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -37,6 +34,7 @@ import com.intellij.packaging.ui.PackagingElementPropertiesPanel;
|
||||
import com.intellij.packaging.ui.PackagingSourceItem;
|
||||
import com.intellij.ui.ScrollPaneFactory;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.ui.treeStructure.SimpleNode;
|
||||
import com.intellij.ui.treeStructure.SimpleTreeBuilder;
|
||||
import com.intellij.ui.treeStructure.SimpleTreeStructure;
|
||||
import com.intellij.ui.treeStructure.WeightBasedComparator;
|
||||
@@ -157,14 +155,17 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
final PackagingElement<?> element = parentNode.getElementIfSingle();
|
||||
if (!checkCanAdd(type, element, parentNode)) return;
|
||||
|
||||
ensureRootIsWritable();
|
||||
CompositePackagingElement<?> parent = element instanceof CompositePackagingElement<?> ? (CompositePackagingElement<?>)element
|
||||
final CompositePackagingElement<?> parent = element instanceof CompositePackagingElement<?> ? (CompositePackagingElement<?>)element
|
||||
: getArtifact().getRootElement();
|
||||
|
||||
final List<? extends PackagingElement<?>> children = type.chooseAndCreate(myContext, getArtifact(), parent);
|
||||
for (PackagingElement<?> child : children) {
|
||||
parent.addOrFindChild(child);
|
||||
}
|
||||
editLayout(new Runnable() {
|
||||
public void run() {
|
||||
for (PackagingElement<?> child : children) {
|
||||
parent.addOrFindChild(child);
|
||||
}
|
||||
}
|
||||
});
|
||||
updateAndSelect(parentNode, children);
|
||||
}
|
||||
|
||||
@@ -210,16 +211,37 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
public void ensureRootIsWritable() {
|
||||
myContext.ensureRootIsWritable(myOriginalArtifact);
|
||||
public void selectNode(@NotNull String parentPath, @NotNull PackagingElement<?> element) {
|
||||
final PackagingElementNode<?> parent = myTree.findCompositeNodeByPath(parentPath);
|
||||
if (parent == null) return;
|
||||
|
||||
for (SimpleNode node : parent.getChildren()) {
|
||||
if (node instanceof PackagingElementNode) {
|
||||
final List<? extends PackagingElement<?>> elements = ((PackagingElementNode<?>)node).getPackagingElements();
|
||||
for (PackagingElement<?> packagingElement : elements) {
|
||||
if (packagingElement.isEqualTo(element)) {
|
||||
myBuilder.select(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void editLayout(Runnable action) {
|
||||
myContext.editLayout(myOriginalArtifact, action);
|
||||
}
|
||||
|
||||
public void removeSelectedElements() {
|
||||
final LayoutTreeSelection selection = myTree.getSelection();
|
||||
if (!checkCanRemove(selection.getNodes())) return;
|
||||
ensureRootIsWritable();
|
||||
|
||||
removeNodes(selection.getNodes());
|
||||
editLayout(new Runnable() {
|
||||
public void run() {
|
||||
removeNodes(selection.getNodes());
|
||||
}
|
||||
});
|
||||
|
||||
myArtifactsEditor.rebuildTries();
|
||||
}
|
||||
|
||||
@@ -321,13 +343,16 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
if (!checkCanAdd(null, targetElement, targetNode)) {
|
||||
return;
|
||||
}
|
||||
ensureRootIsWritable();
|
||||
draggingObject.beforeDrop();
|
||||
List<PackagingElement<?>> toSelect = new ArrayList<PackagingElement<?>>();
|
||||
for (PackagingElement<?> element : draggingObject.createPackagingElements(myContext)) {
|
||||
toSelect.add(element);
|
||||
targetElement.addOrFindChild(element);
|
||||
}
|
||||
final List<PackagingElement<?>> toSelect = new ArrayList<PackagingElement<?>>();
|
||||
editLayout(new Runnable() {
|
||||
public void run() {
|
||||
draggingObject.beforeDrop();
|
||||
for (PackagingElement<?> element : draggingObject.createPackagingElements(myContext)) {
|
||||
toSelect.add(element);
|
||||
targetElement.addOrFindChild(element);
|
||||
}
|
||||
}
|
||||
});
|
||||
updateAndSelect(targetNode, toSelect);
|
||||
myArtifactsEditor.getSourceItemsTree().rebuildTree();
|
||||
}
|
||||
@@ -352,7 +377,7 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
public void updateDraggedImage(Image image, Point dropPoint, Point imageOffset) {
|
||||
}
|
||||
|
||||
public void rename(TreePath path) {
|
||||
public void startRenaming(TreePath path) {
|
||||
myTree.startEditingAtPath(path);
|
||||
}
|
||||
|
||||
@@ -379,20 +404,23 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
mySelectedElementInfo.showPropertiesPanel();
|
||||
}
|
||||
|
||||
public void putIntoDefaultLocations(@NotNull List<? extends PackagingSourceItem> items) {
|
||||
ensureRootIsWritable();
|
||||
|
||||
public void putIntoDefaultLocations(@NotNull final List<? extends PackagingSourceItem> items) {
|
||||
final List<PackagingElement<?>> toSelect = new ArrayList<PackagingElement<?>>();
|
||||
final CompositePackagingElement<?> rootElement = getArtifact().getRootElement();
|
||||
final ArtifactType artifactType = getArtifact().getArtifactType();
|
||||
List<PackagingElement<?>> toSelect = new ArrayList<PackagingElement<?>>();
|
||||
for (PackagingSourceItem item : items) {
|
||||
final String path = artifactType.getDefaultPathFor(item);
|
||||
if (path != null) {
|
||||
final CompositePackagingElement<?> directory = PackagingElementFactory.getInstance().getOrCreateDirectory(rootElement, path);
|
||||
final List<? extends PackagingElement<?>> elements = item.createElements(myContext);
|
||||
toSelect.addAll(directory.addOrFindChildren(elements));
|
||||
editLayout(new Runnable() {
|
||||
public void run() {
|
||||
for (PackagingSourceItem item : items) {
|
||||
final String path = artifactType.getDefaultPathFor(item);
|
||||
if (path != null) {
|
||||
final CompositePackagingElement<?> directory = PackagingElementFactory.getInstance().getOrCreateDirectory(rootElement, path);
|
||||
final List<? extends PackagingElement<?>> elements = item.createElements(myContext);
|
||||
toSelect.addAll(directory.addOrFindChildren(elements));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
myArtifactsEditor.getSourceItemsTree().rebuildTree();
|
||||
updateAndSelect(myTree.getRootPackagingNode(), toSelect);
|
||||
}
|
||||
@@ -432,8 +460,11 @@ public class LayoutTreeComponent implements DnDTarget, Disposable {
|
||||
|
||||
public void save() {
|
||||
if (myCurrentPanel != null && myCurrentPanel.isModified()) {
|
||||
ensureRootIsWritable();
|
||||
myCurrentPanel.apply();
|
||||
editLayout(new Runnable() {
|
||||
public void run() {
|
||||
myCurrentPanel.apply();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.artifacts;
|
||||
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElementUsage;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.elements.PackagingElement;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class UsageInArtifact extends ProjectStructureElementUsage {
|
||||
private Artifact myOriginalArtifact;
|
||||
private final ArtifactsStructureConfigurableContext myContext;
|
||||
private ProjectStructureElement mySourceElement;
|
||||
private ProjectStructureElement myContainingElement;
|
||||
private final String myParentPath;
|
||||
private final PackagingElement<?> myPackagingElement;
|
||||
|
||||
public UsageInArtifact(Artifact originalArtifact, ArtifactsStructureConfigurableContext context, ProjectStructureElement sourceElement,
|
||||
ArtifactProjectStructureElement containingElement,
|
||||
String parentPath, PackagingElement<?> packagingElement) {
|
||||
myOriginalArtifact = originalArtifact;
|
||||
myContext = context;
|
||||
mySourceElement = sourceElement;
|
||||
myContainingElement = containingElement;
|
||||
myParentPath = parentPath;
|
||||
myPackagingElement = packagingElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getSourceElement() {
|
||||
return mySourceElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getContainingElement() {
|
||||
return myContainingElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate() {
|
||||
final Artifact artifact = myContext.getArtifactModel().getArtifactByOriginal(myOriginalArtifact);
|
||||
final ArtifactEditorEx artifactEditor = (ArtifactEditorEx)myContext.getOrCreateEditor(artifact);
|
||||
artifactEditor.getLayoutTreeComponent().selectNode(myParentPath, myPackagingElement);
|
||||
ProjectStructureConfigurable.getInstance(myContext.getProject()).select(myOriginalArtifact, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
return myOriginalArtifact.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myOriginalArtifact.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof UsageInArtifact && ((UsageInArtifact)obj).myOriginalArtifact.equals(myOriginalArtifact);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return myOriginalArtifact.getArtifactType().getIcon();
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -15,10 +15,11 @@
|
||||
*/
|
||||
package com.intellij.openapi.roots.ui.configuration.artifacts.actions;
|
||||
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingElementNode;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.LayoutTreeComponent;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.LayoutTreeComponent;
|
||||
import com.intellij.openapi.roots.ui.configuration.artifacts.nodes.PackagingElementNode;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -39,9 +40,9 @@ public class ArtifactEditorFindUsagesAction extends FindUsagesInProjectStructure
|
||||
return node != null && node.getElementPresentation().getSourceObject() != null;
|
||||
}
|
||||
|
||||
protected Object getSelectedObject() {
|
||||
protected ProjectStructureElement getSelectedElement() {
|
||||
PackagingElementNode<?> node = myLayoutTreeComponent.getSelection().getNodeIfSingle();
|
||||
return node != null ? node.getElementPresentation().getSourceObject() : null;
|
||||
return node != null ? (ProjectStructureElement)node.getElementPresentation().getSourceObject() : null;
|
||||
}
|
||||
|
||||
protected RelativePoint getPointToShowResults() {
|
||||
|
||||
+11
-8
@@ -64,17 +64,20 @@ public class ExtractArtifactAction extends DumbAwareAction {
|
||||
final String name = Messages.showInputDialog(myEditor.getMainComponent(), ProjectBundle.message("label.text.specify.artifact.name"),
|
||||
ProjectBundle.message("dialog.title.extract.artifact"), null);
|
||||
if (name != null) {
|
||||
treeComponent.ensureRootIsWritable();
|
||||
final Project project = myEditor.getContext().getProject();
|
||||
//todo[nik] select type?
|
||||
final ModifiableArtifact artifact = myEditor.getContext().getModifiableArtifactModel().addArtifact(name, PlainArtifactType.getInstance());
|
||||
for (PackagingElement<?> element : selectedElements) {
|
||||
artifact.getRootElement().addOrFindChild(ArtifactUtil.copyWithChildren(element, project));
|
||||
}
|
||||
for (PackagingElement element : selectedElements) {
|
||||
parent.removeChild(element);
|
||||
}
|
||||
parent.addOrFindChild(new ArtifactPackagingElement(project, ArtifactPointerManager.getInstance(project).create(artifact)));
|
||||
treeComponent.editLayout(new Runnable() {
|
||||
public void run() {
|
||||
for (PackagingElement<?> element : selectedElements) {
|
||||
artifact.getRootElement().addOrFindChild(ArtifactUtil.copyWithChildren(element, project));
|
||||
}
|
||||
for (PackagingElement element : selectedElements) {
|
||||
parent.removeChild(element);
|
||||
}
|
||||
parent.addOrFindChild(new ArtifactPackagingElement(project, ArtifactPointerManager.getInstance(project).create(artifact)));
|
||||
}
|
||||
});
|
||||
treeComponent.rebuildTree();
|
||||
}
|
||||
}
|
||||
|
||||
+17
-14
@@ -56,28 +56,31 @@ public class InlineArtifactAction extends DumbAwareAction {
|
||||
final PackagingElementNode<?> node = selection.getNodeIfSingle();
|
||||
if (node == null || !(element instanceof ArtifactPackagingElement)) return;
|
||||
|
||||
CompositePackagingElement<?> parent = node.getParentElement(element);
|
||||
final CompositePackagingElement<?> parent = node.getParentElement(element);
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
if (!treeComponent.checkCanRemove(selection.getNodes())) return;
|
||||
if (!treeComponent.checkCanAdd(null, parent, node)) return;
|
||||
|
||||
treeComponent.ensureRootIsWritable();
|
||||
parent.removeChild(element);
|
||||
final ArtifactEditorContext context = myEditor.getContext();
|
||||
final Artifact artifact = ((ArtifactPackagingElement)element).findArtifact(context);
|
||||
if (artifact != null) {
|
||||
final CompositePackagingElement<?> rootElement = artifact.getRootElement();
|
||||
if (rootElement instanceof ArtifactRootElement<?>) {
|
||||
for (PackagingElement<?> child : rootElement.getChildren()) {
|
||||
parent.addOrFindChild(ArtifactUtil.copyWithChildren(child, context.getProject()));
|
||||
treeComponent.editLayout(new Runnable() {
|
||||
public void run() {
|
||||
parent.removeChild(element);
|
||||
final ArtifactEditorContext context = myEditor.getContext();
|
||||
final Artifact artifact = ((ArtifactPackagingElement)element).findArtifact(context);
|
||||
if (artifact != null) {
|
||||
final CompositePackagingElement<?> rootElement = artifact.getRootElement();
|
||||
if (rootElement instanceof ArtifactRootElement<?>) {
|
||||
for (PackagingElement<?> child : rootElement.getChildren()) {
|
||||
parent.addOrFindChild(ArtifactUtil.copyWithChildren(child, context.getProject()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
parent.addOrFindChild(ArtifactUtil.copyWithChildren(rootElement, context.getProject()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
parent.addOrFindChild(ArtifactUtil.copyWithChildren(rootElement, context.getProject()));
|
||||
}
|
||||
}
|
||||
});
|
||||
treeComponent.rebuildTree();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-5
@@ -24,6 +24,7 @@ import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElement;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -80,11 +81,18 @@ public class MoveElementAction extends DumbAwareAction {
|
||||
|
||||
if (myLayoutTreeComponent.checkCanRemove(Collections.singletonList(node))
|
||||
&& myLayoutTreeComponent.checkCanAdd(null, parentElement, parent)) {
|
||||
myLayoutTreeComponent.ensureRootIsWritable();
|
||||
final int index = parentElement.getChildren().indexOf(element);
|
||||
final PackagingElement<?> moved = parentElement.moveChild(index, myDirection);
|
||||
if (moved != null) {
|
||||
myLayoutTreeComponent.updateAndSelect(parent, Collections.singletonList(moved));
|
||||
final List<PackagingElement<?>> toSelect = new ArrayList<PackagingElement<?>>();
|
||||
myLayoutTreeComponent.editLayout(new Runnable() {
|
||||
public void run() {
|
||||
final int index = parentElement.getChildren().indexOf(element);
|
||||
final PackagingElement<?> moved = parentElement.moveChild(index, myDirection);
|
||||
if (moved != null) {
|
||||
toSelect.add(moved);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!toSelect.isEmpty()) {
|
||||
myLayoutTreeComponent.updateAndSelect(parent, toSelect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -53,7 +53,6 @@ public class RenamePackagingElementAction extends DumbAwareAction {
|
||||
final PackagingElementNode<?> node = selection.getNodeIfSingle();
|
||||
if (node == null) return;
|
||||
final TreePath path = selection.getPath(node);
|
||||
myArtifactEditor.getLayoutTreeComponent().ensureRootIsWritable();
|
||||
myArtifactEditor.getLayoutTreeComponent().rename(path);
|
||||
myArtifactEditor.getLayoutTreeComponent().startRenaming(path);
|
||||
}
|
||||
}
|
||||
|
||||
+14
@@ -131,4 +131,18 @@ public class PackagingElementNode<E extends PackagingElement<?>> extends Artifac
|
||||
public ArtifactEditorContext getContext() {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CompositePackagingElementNode findCompositeChild(@NotNull String name) {
|
||||
final SimpleNode[] children = getChildren();
|
||||
for (SimpleNode child : children) {
|
||||
if (child instanceof CompositePackagingElementNode) {
|
||||
final CompositePackagingElementNode composite = (CompositePackagingElementNode)child;
|
||||
if (name.equals(composite.getFirstElement().getName())) {
|
||||
return composite;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-9
@@ -100,22 +100,37 @@ public class PutSourceItemIntoParentAndLinkViaManifestAction extends AnAction {
|
||||
|
||||
final Artifact artifact = parentsInfo.getGrandparentArtifact();
|
||||
final ArtifactEditorContext context = myArtifactEditor.getContext();
|
||||
context.ensureRootIsWritable(artifact);
|
||||
context.ensureRootIsWritable(parentsInfo.getParentArtifact());
|
||||
//todo[nik] improve
|
||||
final Runnable emptyRunnable = new Runnable() {
|
||||
public void run() {
|
||||
}
|
||||
};
|
||||
context.editLayout(artifact, emptyRunnable);
|
||||
context.editLayout(parentsInfo.getParentArtifact(), emptyRunnable);
|
||||
parentsInfo = findParentAndGrandParent(myArtifactEditor.getArtifact());//find elements under modifiable root
|
||||
if (parentsInfo == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CompositePackagingElement<?> grandParent = parentsInfo.getGrandparentElement();
|
||||
List<String> classpath = new ArrayList<String>();
|
||||
for (PackagingSourceItem item : items) {
|
||||
final List<? extends PackagingElement<?>> elements = item.createElements(context);
|
||||
grandParent.addOrFindChildren(elements);
|
||||
classpath.addAll(ManifestFileUtil.getClasspathForElements(elements, context, artifact.getArtifactType()));
|
||||
}
|
||||
final List<String> classpath = new ArrayList<String>();
|
||||
context.editLayout(artifact, new Runnable() {
|
||||
public void run() {
|
||||
for (PackagingSourceItem item : items) {
|
||||
final List<? extends PackagingElement<?>> elements = item.createElements(context);
|
||||
grandParent.addOrFindChildren(elements);
|
||||
classpath.addAll(ManifestFileUtil.getClasspathForElements(elements, context, artifact.getArtifactType()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final ArtifactEditor parentArtifactEditor = context.getOrCreateEditor(parentsInfo.getParentArtifact());
|
||||
parentArtifactEditor.addToClasspath(parentsInfo.getParentElement(), classpath);
|
||||
final ParentElementsInfo finalParentsInfo = parentsInfo;
|
||||
context.editLayout(parentsInfo.getParentArtifact(), new Runnable() {
|
||||
public void run() {
|
||||
parentArtifactEditor.addToClasspath(finalParentsInfo.getParentElement(), classpath);
|
||||
}
|
||||
});
|
||||
((ArtifactEditorImpl)context.getOrCreateEditor(parentsInfo.getGrandparentArtifact())).rebuildTries();
|
||||
}
|
||||
|
||||
|
||||
+29
-14
@@ -30,9 +30,9 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableEditor;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.ui.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
@@ -40,15 +40,20 @@ import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurable {
|
||||
protected String myLevel;
|
||||
@@ -91,18 +96,28 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
|
||||
}
|
||||
|
||||
protected void loadTree() {
|
||||
final LibraryTablesRegistrar registrar = LibraryTablesRegistrar.getInstance();
|
||||
|
||||
final LibrariesModifiableModel provider = myContext.myLevel2Providers.get(myLevel);
|
||||
createLibrariesNode(registrar.getLibraryTableByLevel(myLevel, myProject), provider,
|
||||
myContext.createModifiableModelProvider(myLevel, false));
|
||||
final LibraryTable libraryTable = LibraryTablesRegistrar.getInstance().getLibraryTableByLevel(myLevel, myProject);
|
||||
createLibrariesNode(myContext.createModifiableModelProvider(myLevel, false), new LibrariesModifiableModel(libraryTable, myProject));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
|
||||
final List<ProjectStructureElement> result = new ArrayList<ProjectStructureElement>();
|
||||
//todo[nik] improve
|
||||
for (int i = 0; i < myRoot.getChildCount(); i++) {
|
||||
final TreeNode node = myRoot.getChildAt(i);
|
||||
if (node instanceof MyNode) {
|
||||
final NamedConfigurable configurable = ((MyNode)node).getConfigurable();
|
||||
if (configurable instanceof LibraryConfigurable) {
|
||||
result.add(new LibraryProjectStructureElement(myContext, ((LibraryConfigurable)configurable).getEditableObject()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void createLibrariesNode(final LibraryTable table,
|
||||
LibrariesModifiableModel provider,
|
||||
final LibraryTableModifiableModelProvider modelProvider) {
|
||||
provider = new LibrariesModifiableModel(table, myProject);
|
||||
private void createLibrariesNode(final LibraryTableModifiableModelProvider modelProvider, final LibrariesModifiableModel provider) {
|
||||
final Library[] libraries = provider.getLibraries();
|
||||
for (Library library : libraries) {
|
||||
myRoot.add(new MyNode(new LibraryConfigurable(modelProvider, library, myProject, TREE_UPDATER)));
|
||||
@@ -136,6 +151,7 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
|
||||
new LibraryConfigurable(myContext.createModifiableModelProvider(level, false), library, myProject, TREE_UPDATER);
|
||||
final MyNode node = new MyNode(configurable);
|
||||
addNode(node, myRoot);
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new LibraryProjectStructureElement(myContext, library));
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -178,8 +194,7 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
|
||||
final LibraryTable table = library.getTable();
|
||||
if (table != null) {
|
||||
getModelProvider(true).getModifiableModel().removeLibrary(library);
|
||||
myContext.invalidateModules(myContext.myLibraryDependencyCache.get(library));
|
||||
myContext.myLibraryDependencyCache.remove(library);
|
||||
myContext.getDaemonAnalyzer().removeElement(new LibraryProjectStructureElement(myContext, library));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+66
-74
@@ -18,7 +18,6 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot;
|
||||
import com.intellij.facet.Facet;
|
||||
import com.intellij.ide.CommonActionsManager;
|
||||
import com.intellij.ide.TreeExpander;
|
||||
import com.intellij.ide.impl.convert.ProjectFileVersion;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
@@ -31,10 +30,15 @@ import com.intellij.openapi.project.ProjectBundle;
|
||||
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.ProjectStructureDaemonAnalyzer;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolder;
|
||||
import com.intellij.openapi.ui.MasterDetailsComponent;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.ui.ColoredTreeCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.TreeSpeedSearch;
|
||||
@@ -42,11 +46,9 @@ import com.intellij.ui.TreeToolTipHandler;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.navigation.Place;
|
||||
import com.intellij.util.Icons;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import com.intellij.util.containers.Convertor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.tree.TreeUtil;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -74,7 +76,7 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
|
||||
public void init(StructureConfigurableContext context) {
|
||||
myContext = context;
|
||||
myContext.addCacheUpdateListener(new Runnable() {
|
||||
myContext.getDaemonAnalyzer().addListener(new Runnable() {
|
||||
public void run() {
|
||||
if (!myTree.isShowing()) return;
|
||||
|
||||
@@ -149,81 +151,54 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
if (value instanceof MyNode) {
|
||||
final MyNode node = (MyNode)value;
|
||||
|
||||
if (node.getConfigurable() == null) {
|
||||
final NamedConfigurable namedConfigurable = node.getConfigurable();
|
||||
if (namedConfigurable == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String displayName = node.getDisplayName();
|
||||
final Icon icon = node.getConfigurable().getIcon(expanded);
|
||||
final Icon icon = namedConfigurable.getIcon(expanded);
|
||||
setIcon(icon);
|
||||
setToolTipText(null);
|
||||
setFont(UIUtil.getTreeFont());
|
||||
if (node.isDisplayInBold()){
|
||||
append(displayName, SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
|
||||
} else {
|
||||
final Object object = node.getConfigurable().getEditableObject();
|
||||
final boolean unused = myContext.isUnused(object);
|
||||
final StructureConfigurableContext.ValidityLevel level = myContext.isInvalid(object);
|
||||
final boolean invalid = level != StructureConfigurableContext.ValidityLevel.VALID;
|
||||
if (unused || invalid){
|
||||
Color fg = unused
|
||||
? UIUtil.getTextInactiveTextColor()
|
||||
: selected && hasFocus ? UIUtil.getTreeSelectionForeground() : UIUtil.getTreeForeground();
|
||||
append(displayName, new SimpleTextAttributes(invalid ? SimpleTextAttributes.STYLE_WAVED : SimpleTextAttributes.STYLE_PLAIN,
|
||||
fg,
|
||||
level == StructureConfigurableContext.ValidityLevel.ERROR ? Color.RED : Color.GRAY));
|
||||
setToolTipText(composeTooltipMessage(invalid, object, displayName, unused));
|
||||
}
|
||||
else {
|
||||
append(displayName, selected && hasFocus ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
|
||||
|
||||
SimpleTextAttributes textAttributes =
|
||||
selected && hasFocus ? SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES;
|
||||
if (node.isDisplayInBold()) {
|
||||
textAttributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
|
||||
} else if (namedConfigurable instanceof ProjectStructureElementConfigurable) {
|
||||
final ProjectStructureElement projectStructureElement =
|
||||
((ProjectStructureElementConfigurable)namedConfigurable).getProjectStructureElement();
|
||||
if (projectStructureElement != null) {
|
||||
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
|
||||
final boolean unused = daemonAnalyzer.isUnused(projectStructureElement);
|
||||
final ProjectStructureProblemsHolder problemsHolder = daemonAnalyzer.getProblemsHolder(projectStructureElement);
|
||||
if (problemsHolder == null) {
|
||||
daemonAnalyzer.queueUpdate(projectStructureElement, true, false);
|
||||
}
|
||||
final ProjectStructureProblemDescription.Severity level = problemsHolder != null ? problemsHolder.getSeverity() : null;
|
||||
final boolean invalid = level != null;
|
||||
if (unused || invalid) {
|
||||
Color fg = unused
|
||||
? UIUtil.getTextInactiveTextColor()
|
||||
: selected && hasFocus ? UIUtil.getTreeSelectionForeground() : UIUtil.getTreeForeground();
|
||||
textAttributes = new SimpleTextAttributes(invalid ? SimpleTextAttributes.STYLE_WAVED : SimpleTextAttributes.STYLE_PLAIN, fg,
|
||||
level == ProjectStructureProblemDescription.Severity.ERROR ? Color.RED : Color.GRAY);
|
||||
String text = problemsHolder != null ? problemsHolder.composeTooltipMessage() : "";
|
||||
if (unused) {
|
||||
text += ProjectBundle.message("project.roots.tooltip.unused", displayName);
|
||||
}
|
||||
setToolTipText(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
append(displayName, textAttributes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
private String composeTooltipMessage(final boolean invalid, final Object object, final String displayName, final boolean unused) {
|
||||
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
if (invalid) {
|
||||
if (object instanceof Module) {
|
||||
final Module module = (Module)object;
|
||||
final Map<String, Set<String>> problems = myContext.myValidityCache.get(module);
|
||||
|
||||
if (problems.containsKey(StructureConfigurableContext.DUPLICATE_MODULE_NAME)) {
|
||||
buf.append(StructureConfigurableContext.DUPLICATE_MODULE_NAME).append("\n");
|
||||
}
|
||||
|
||||
if (problems.containsKey(StructureConfigurableContext.NO_JDK)){
|
||||
buf.append(StructureConfigurableContext.NO_JDK).append("\n");
|
||||
}
|
||||
final Set<String> deletedLibraries = problems.get(StructureConfigurableContext.DELETED_LIBRARIES);
|
||||
if (deletedLibraries != null) {
|
||||
buf.append(ProjectBundle.message("project.roots.library.problem.message", deletedLibraries.size()));
|
||||
for (String problem : deletedLibraries) {
|
||||
if (deletedLibraries.size() > 1) {
|
||||
buf.append(" - ");
|
||||
}
|
||||
buf.append("\'").append(problem).append("\'").append("\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
buf.append(ProjectBundle.message("project.roots.tooltip.library.misconfigured", displayName)).append("\n");
|
||||
}
|
||||
}
|
||||
if (unused) {
|
||||
buf.append(ProjectBundle.message("project.roots.tooltip.unused", displayName));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(buf);
|
||||
}
|
||||
}
|
||||
|
||||
public void disposeUIResources() {
|
||||
if (myUiDisposed) return;
|
||||
|
||||
@@ -232,16 +207,12 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
myUiDisposed = true;
|
||||
|
||||
myAutoScrollHandler.cancelAllRequests();
|
||||
myContext.myUpdateDependenciesAlarm.cancelAllRequests();
|
||||
myContext.myUpdateDependenciesAlarm.addRequest(new Runnable(){
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run() {
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
dispose();
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
protected void addCollapseExpandActions(final List<AnAction> result) {
|
||||
@@ -267,6 +238,19 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
result.add(actionsManager.createCollapseAllAction(expander, myTree));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ProjectStructureElement getSelectedElement() {
|
||||
final TreePath selectionPath = myTree.getSelectionPath();
|
||||
if (selectionPath != null && selectionPath.getLastPathComponent() instanceof MyNode) {
|
||||
MyNode node = (MyNode)selectionPath.getLastPathComponent();
|
||||
final NamedConfigurable configurable = node.getConfigurable();
|
||||
if (configurable instanceof ProjectStructureElementConfigurable) {
|
||||
return ((ProjectStructureElementConfigurable)configurable).getProjectStructureElement();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class MyFindUsagesAction extends FindUsagesInProjectStructureActionBase {
|
||||
|
||||
public MyFindUsagesAction(JComponent parentComponent) {
|
||||
@@ -287,8 +271,8 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
return myContext;
|
||||
}
|
||||
|
||||
protected Object getSelectedObject() {
|
||||
return BaseStructureConfigurable.this.getSelectedObject();
|
||||
protected ProjectStructureElement getSelectedElement() {
|
||||
return BaseStructureConfigurable.this.getSelectedElement();
|
||||
}
|
||||
|
||||
protected RelativePoint getPointToShowResults() {
|
||||
@@ -313,10 +297,18 @@ public abstract class BaseStructureConfigurable extends MasterDetailsComponent i
|
||||
myTree.setShowsRootHandles(false);
|
||||
loadTree();
|
||||
}
|
||||
for (ProjectStructureElement element : getProjectStructureElements()) {
|
||||
myContext.getDaemonAnalyzer().queueUpdate(element, false, true);
|
||||
}
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
protected abstract void loadTree();
|
||||
|
||||
|
||||
|
||||
+32
-53
@@ -20,36 +20,29 @@ import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.impl.OrderEntryUtil;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElementUsage;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Set;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class FindUsagesInProjectStructureActionBase extends AnAction implements DumbAware {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.projectRoot.FindUsagesInProjectStructureActionBase");
|
||||
private static final Icon FIND_ICON = IconLoader.getIcon("/actions/find.png");
|
||||
private final JComponent myParentComponent;
|
||||
private final Project myProject;
|
||||
@@ -68,60 +61,46 @@ public abstract class FindUsagesInProjectStructureActionBase extends AnAction im
|
||||
protected abstract boolean isEnabled();
|
||||
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final Object selectedObject = getSelectedObject();
|
||||
if (selectedObject == null) return;
|
||||
final ProjectStructureElement selected = getSelectedElement();
|
||||
if (selected == null) return;
|
||||
|
||||
final Set<String> dependencies = getContext().getCachedDependencies(selectedObject, true);
|
||||
if (dependencies == null || dependencies.isEmpty()) {
|
||||
Messages.showInfoMessage(myParentComponent, FindBundle.message("find.usage.view.no.usages.text"),
|
||||
FindBundle.message("find.pointcut.applications.not.found.title"));
|
||||
final Collection<ProjectStructureElementUsage> usages = getContext().getDaemonAnalyzer().getUsages(selected);
|
||||
if (usages.isEmpty()) {
|
||||
Messages.showInfoMessage(myParentComponent, FindBundle.message("find.usage.view.no.usages.text"), FindBundle.message("find.pointcut.applications.not.found.title"));
|
||||
return;
|
||||
}
|
||||
RelativePoint point = getPointToShowResults();
|
||||
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>(ProjectBundle.message("dependencies.used.in.popup.title"),
|
||||
ArrayUtil.toStringArray(dependencies)) {
|
||||
|
||||
public PopupStep onChosen(final String nameToSelect, final boolean finalChoice) {
|
||||
navigateToObject(nameToSelect, selectedObject);
|
||||
RelativePoint point = getPointToShowResults();
|
||||
final ProjectStructureElementUsage[] usagesArray = usages.toArray(new ProjectStructureElementUsage[usages.size()]);
|
||||
Arrays.sort(usagesArray, new Comparator<ProjectStructureElementUsage>() {
|
||||
public int compare(ProjectStructureElementUsage o1, ProjectStructureElementUsage o2) {
|
||||
return o1.getPresentableName().compareToIgnoreCase(o2.getPresentableName());
|
||||
}
|
||||
});
|
||||
|
||||
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<ProjectStructureElementUsage>(ProjectBundle.message("dependencies.used.in.popup.title"), usagesArray) {
|
||||
@Override
|
||||
public PopupStep onChosen(final ProjectStructureElementUsage selected, final boolean finalChoice) {
|
||||
selected.navigate();
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
public Icon getIconFor(String selection) {
|
||||
final Module module = getContext().myModulesConfigurator.getModule(selection);
|
||||
LOG.assertTrue(module != null, selection + " was not found");
|
||||
return module.getModuleType().getNodeIcon(false);
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(ProjectStructureElementUsage value) {
|
||||
return value.getPresentableName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIconFor(ProjectStructureElementUsage selection) {
|
||||
return selection.getIcon();
|
||||
}
|
||||
|
||||
}).show(point);
|
||||
}
|
||||
|
||||
private void navigateToObject(final String moduleName, final @NotNull Object selectedObject) {
|
||||
ModulesConfigurator modulesConfigurator = getContext().myModulesConfigurator;
|
||||
Module module = modulesConfigurator.getModule(moduleName);
|
||||
if (module == null) {
|
||||
ProjectStructureConfigurable.getInstance(myProject).select(moduleName, null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
ModuleRootModel rootModel = modulesConfigurator.getRootModel(module);
|
||||
OrderEntry entry;
|
||||
if (selectedObject instanceof Library) {
|
||||
entry = OrderEntryUtil.findLibraryOrderEntry(rootModel, (Library)selectedObject);
|
||||
}
|
||||
else if (selectedObject instanceof Module) {
|
||||
entry = OrderEntryUtil.findModuleOrderEntry(rootModel, (Module)selectedObject);
|
||||
}
|
||||
else if (selectedObject instanceof Sdk) {
|
||||
entry = OrderEntryUtil.findJdkOrderEntry(rootModel, (Sdk)selectedObject);
|
||||
}
|
||||
else {
|
||||
entry = null;
|
||||
}
|
||||
ModuleStructureConfigurable.getInstance(myProject).selectOrderEntry(module, entry);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract Object getSelectedObject();
|
||||
protected abstract ProjectStructureElement getSelectedElement();
|
||||
|
||||
protected StructureConfigurableContext getContext() {
|
||||
return ModuleStructureConfigurable.getInstance(myProject).getContext();
|
||||
|
||||
+13
-3
@@ -17,11 +17,13 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot;
|
||||
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.projectRoots.ui.SdkEditor;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.ui.navigation.History;
|
||||
import com.intellij.ui.navigation.Place;
|
||||
@@ -35,16 +37,24 @@ import javax.swing.*;
|
||||
* User: anna
|
||||
* Date: 05-Jun-2006
|
||||
*/
|
||||
public class JdkConfigurable extends NamedConfigurable<Sdk> implements Place.Navigator {
|
||||
public class JdkConfigurable extends ProjectStructureElementConfigurable<Sdk> implements Place.Navigator {
|
||||
private final ProjectJdkImpl myProjectJdk;
|
||||
private final SdkEditor mySdkEditor;
|
||||
private SdkProjectStructureElement myProjectStructureElement;
|
||||
|
||||
public JdkConfigurable(final ProjectJdkImpl projectJdk,
|
||||
final ProjectJdksModel configurable,
|
||||
final Runnable updateTree, @NotNull History history) {
|
||||
final Runnable updateTree, @NotNull History history, Project project) {
|
||||
super(true, updateTree);
|
||||
myProjectJdk = projectJdk;
|
||||
mySdkEditor = new SdkEditor(configurable, history, myProjectJdk);
|
||||
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(project).getContext();
|
||||
myProjectStructureElement = new SdkProjectStructureElement(context, myProjectJdk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getProjectStructureElement() {
|
||||
return myProjectStructureElement;
|
||||
}
|
||||
|
||||
public void setDisplayName(final String name) {
|
||||
|
||||
+21
-4
@@ -29,16 +29,22 @@ import com.intellij.openapi.projectRoots.SdkModel;
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement;
|
||||
import com.intellij.openapi.ui.MasterDetailsComponent;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.tree.TreePath;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@State(
|
||||
name = "JdkListConfigurable.UI",
|
||||
@@ -120,14 +126,26 @@ public class JdkListConfigurable extends BaseStructureConfigurable {
|
||||
protected void loadTree() {
|
||||
final HashMap<Sdk,Sdk> sdks = myJdksTreeModel.getProjectJdks();
|
||||
for (Sdk sdk : sdks.keySet()) {
|
||||
final JdkConfigurable configurable = new JdkConfigurable((ProjectJdkImpl)sdks.get(sdk), myJdksTreeModel, TREE_UPDATER, myHistory);
|
||||
final JdkConfigurable configurable = new JdkConfigurable((ProjectJdkImpl)sdks.get(sdk), myJdksTreeModel, TREE_UPDATER, myHistory,
|
||||
myProject);
|
||||
addNode(new MyNode(configurable), myRoot);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
|
||||
final List<ProjectStructureElement> result = new ArrayList<ProjectStructureElement>();
|
||||
for (Sdk sdk : myJdksTreeModel.getProjectJdks().values()) {
|
||||
result.add(new SdkProjectStructureElement(myContext, sdk));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean addJdkNode(final Sdk jdk, final boolean selectInTree) {
|
||||
if (!myUiDisposed) {
|
||||
addNode(new MyNode(new JdkConfigurable((ProjectJdkImpl)jdk, myJdksTreeModel, TREE_UPDATER, myHistory)), myRoot);
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new SdkProjectStructureElement(myContext, jdk));
|
||||
addNode(new MyNode(new JdkConfigurable((ProjectJdkImpl)jdk, myJdksTreeModel, TREE_UPDATER, myHistory, myProject)), myRoot);
|
||||
if (selectInTree) {
|
||||
selectNodeInTree(MasterDetailsComponent.findNodeByObject(myRoot, jdk));
|
||||
}
|
||||
@@ -188,8 +206,7 @@ public class JdkListConfigurable extends BaseStructureConfigurable {
|
||||
|
||||
protected void removeJdk(final Sdk jdk) {
|
||||
myJdksTreeModel.removeJdk(jdk);
|
||||
myContext.myJdkDependencyCache.remove(jdk);
|
||||
myContext.myValidityCache.clear();
|
||||
myContext.getDaemonAnalyzer().removeElement(new SdkProjectStructureElement(myContext, jdk));
|
||||
}
|
||||
|
||||
protected
|
||||
|
||||
+16
-2
@@ -24,7 +24,8 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryTableEditor;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.LibraryProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -36,13 +37,14 @@ import javax.swing.*;
|
||||
* User: anna
|
||||
* Date: 02-Jun-2006
|
||||
*/
|
||||
public class LibraryConfigurable extends NamedConfigurable<Library> {
|
||||
public class LibraryConfigurable extends ProjectStructureElementConfigurable<Library> {
|
||||
private static final Icon ICON = IconLoader.getIcon("/modules/library.png");
|
||||
|
||||
private LibraryTableEditor myLibraryEditor;
|
||||
private final Library myLibrary;
|
||||
private final LibraryTableModifiableModelProvider myModel;
|
||||
private final Project myProject;
|
||||
private final LibraryProjectStructureElement myProjectStructureElement;
|
||||
|
||||
protected LibraryConfigurable(final LibraryTableModifiableModelProvider libraryTable,
|
||||
final Library library,
|
||||
@@ -52,10 +54,17 @@ public class LibraryConfigurable extends NamedConfigurable<Library> {
|
||||
myModel = libraryTable;
|
||||
myProject = project;
|
||||
myLibrary = library;
|
||||
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(myProject).getContext();
|
||||
myProjectStructureElement = new LibraryProjectStructureElement(context, myLibrary);
|
||||
}
|
||||
|
||||
public JComponent createOptionsPanel() {
|
||||
myLibraryEditor = LibraryTableEditor.editLibrary(myModel, myLibrary, myProject);
|
||||
myLibraryEditor.addListener(new Runnable() {
|
||||
public void run() {
|
||||
ModuleStructureConfigurable.getInstance(myProject).getContext().getDaemonAnalyzer().queueUpdate(myProjectStructureElement);
|
||||
}
|
||||
});
|
||||
return myLibraryEditor.getComponent();
|
||||
}
|
||||
|
||||
@@ -63,6 +72,11 @@ public class LibraryConfigurable extends NamedConfigurable<Library> {
|
||||
return myLibraryEditor != null && myLibraryEditor.hasChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getProjectStructureElement() {
|
||||
return myProjectStructureElement;
|
||||
}
|
||||
|
||||
public void apply() throws ConfigurationException {
|
||||
//do nothing
|
||||
}
|
||||
|
||||
+12
-3
@@ -23,12 +23,13 @@ import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.navigation.Place;
|
||||
import com.intellij.ui.navigation.History;
|
||||
import com.intellij.ui.navigation.Place;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,10 +40,11 @@ import javax.swing.*;
|
||||
* User: anna
|
||||
* Date: 04-Jun-2006
|
||||
*/
|
||||
public class ModuleConfigurable extends NamedConfigurable<Module> implements Place.Navigator {
|
||||
public class ModuleConfigurable extends ProjectStructureElementConfigurable<Module> implements Place.Navigator {
|
||||
private final Module myModule;
|
||||
private final ModulesConfigurator myConfigurator;
|
||||
private String myModuleName;
|
||||
private final ModuleProjectStructureElement myProjectStructureElement;
|
||||
|
||||
public ModuleConfigurable(ModulesConfigurator modulesConfigurator,
|
||||
Module module,
|
||||
@@ -51,6 +53,8 @@ public class ModuleConfigurable extends NamedConfigurable<Module> implements Pla
|
||||
myModule = module;
|
||||
myModuleName = myModule.getName();
|
||||
myConfigurator = modulesConfigurator;
|
||||
final StructureConfigurableContext context = ModuleStructureConfigurable.getInstance(myModule.getProject()).getContext();
|
||||
myProjectStructureElement = new ModuleProjectStructureElement(context, myModule);
|
||||
}
|
||||
|
||||
public void setDisplayName(String name) {
|
||||
@@ -69,6 +73,11 @@ public class ModuleConfigurable extends NamedConfigurable<Module> implements Pla
|
||||
myConfigurator.setModified(!Comparing.strEqual(myModuleName, myModule.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getProjectStructureElement() {
|
||||
return myProjectStructureElement;
|
||||
}
|
||||
|
||||
public Module getEditableObject() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
+17
-12
@@ -47,6 +47,7 @@ import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.*;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
@@ -136,6 +137,16 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
myUiDisposed = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Collection<? extends ProjectStructureElement> getProjectStructureElements() {
|
||||
final List<ProjectStructureElement> result = new ArrayList<ProjectStructureElement>();
|
||||
for (Module module : myModuleManager.getModules()) {
|
||||
result.add(new ModuleProjectStructureElement(myContext, module));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void updateSelection(@Nullable final NamedConfigurable configurable) {
|
||||
FacetStructureConfigurable.getInstance(myProject).disposeMultipleSettingsEditor();
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
@@ -299,7 +310,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
node.removeFromParent();
|
||||
((DefaultTreeModel)myTree.getModel()).reload(parent);
|
||||
}
|
||||
myContext.invalidateModules(myContext.myLibraryDependencyCache.get(library));
|
||||
myContext.getDaemonAnalyzer().removeElement(new LibraryProjectStructureElement(myContext, library));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +342,6 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
public void disposeUIResources() {
|
||||
super.disposeUIResources();
|
||||
myFacetEditorFacade.clearMaps();
|
||||
myContext.clearCaches();
|
||||
myContext.myModulesConfigurator.disposeUIResources();
|
||||
ModuleStructureConfigurable.super.disposeUIResources();
|
||||
}
|
||||
@@ -445,12 +455,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
}
|
||||
modelProxy.addLibraryEntry(library);
|
||||
Set<String> modules = myContext.myLibraryDependencyCache.get(library);
|
||||
if (modules == null) {
|
||||
modules = new HashSet<String>();
|
||||
myContext.myLibraryDependencyCache.put(library, modules);
|
||||
}
|
||||
modules.add(module.getName());
|
||||
myContext.getDaemonAnalyzer().queueUpdate(new ModuleProjectStructureElement(myContext, module));
|
||||
myTree.repaint();
|
||||
}
|
||||
|
||||
@@ -500,7 +505,9 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
myFacetEditorFacade.addFacetsNodes(module, node);
|
||||
((DefaultTreeModel)myTree.getModel()).reload(parent);
|
||||
selectNodeInTree(node);
|
||||
myContext.myValidityCache.clear(); //missing modules added
|
||||
final ProjectStructureDaemonAnalyzer daemonAnalyzer = myContext.getDaemonAnalyzer();
|
||||
daemonAnalyzer.queueUpdate(new ModuleProjectStructureElement(myContext, module));
|
||||
daemonAnalyzer.clearAllProblems(); //missing modules added
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -670,9 +677,7 @@ public class ModuleStructureConfigurable extends BaseStructureConfigurable imple
|
||||
}
|
||||
List<Facet> removed = modulesConfigurator.getFacetsConfigurator().removeAllFacets(module);
|
||||
FacetStructureConfigurable.getInstance(myProject).removeFacetNodes(removed);
|
||||
myContext.myValidityCache.remove(module);
|
||||
myContext.invalidateModules(myContext.myModulesDependencyCache.get(module));
|
||||
myContext.myModulesDependencyCache.remove(module);
|
||||
myContext.getDaemonAnalyzer().removeElement(new ModuleProjectStructureElement(myContext, module));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
|
||||
import com.intellij.openapi.ui.NamedConfigurable;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectStructureElementConfigurable<T> extends NamedConfigurable<T> {
|
||||
protected ProjectStructureElementConfigurable() {
|
||||
}
|
||||
|
||||
protected ProjectStructureElementConfigurable(boolean isNameEditable, @Nullable Runnable updateTree) {
|
||||
super(isNameEditable, updateTree);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract ProjectStructureElement getProjectStructureElement();
|
||||
|
||||
}
|
||||
+13
-356
@@ -16,362 +16,55 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablePresentation;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureConfigurableContext implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#" + StructureConfigurableContext.class.getName());
|
||||
|
||||
public enum ValidityLevel { VALID, WARNING, ERROR }
|
||||
|
||||
public static final String NO_JDK = ProjectBundle.message("project.roots.module.jdk.problem.message");
|
||||
public static final String DUPLICATE_MODULE_NAME = ProjectBundle.message("project.roots.module.duplicate.name.message");
|
||||
@NonNls public static final String DELETED_LIBRARIES = "lib";
|
||||
|
||||
public final Map<Library, Set<String>> myLibraryDependencyCache = new HashMap<Library, Set<String>>();
|
||||
public final Map<Sdk, Set<String>> myJdkDependencyCache = new HashMap<Sdk, Set<String>>();
|
||||
public final Map<Module, Map<String, Set<String>>> myValidityCache = new HashMap<Module, Map<String, Set<String>>>();
|
||||
public final Map<Library, ValidityLevel> myLibraryPathValidityCache = new HashMap<Library, ValidityLevel>(); //can be invalidated on startup only
|
||||
public final Map<Module, Set<String>> myModulesDependencyCache = new HashMap<Module, Set<String>>();
|
||||
|
||||
private final ModuleManager myModuleManager;
|
||||
private final ProjectStructureDaemonAnalyzer myDaemonAnalyzer;
|
||||
public final ModulesConfigurator myModulesConfigurator;
|
||||
private boolean myDisposed;
|
||||
|
||||
public final Alarm myUpdateDependenciesAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
|
||||
public final Alarm myReloadProjectAlarm = new Alarm();
|
||||
|
||||
private final List<Runnable> myCacheUpdaters = new ArrayList<Runnable>();
|
||||
|
||||
|
||||
public final Map<String, LibrariesModifiableModel> myLevel2Providers = new THashMap<String, LibrariesModifiableModel>();
|
||||
private final Project myProject;
|
||||
|
||||
|
||||
public StructureConfigurableContext(Project project, final ModuleManager moduleManager, final ModulesConfigurator modulesConfigurator) {
|
||||
public StructureConfigurableContext(Project project, final ModulesConfigurator modulesConfigurator) {
|
||||
myProject = project;
|
||||
myModuleManager = moduleManager;
|
||||
myModulesConfigurator = modulesConfigurator;
|
||||
Disposer.register(project, this);
|
||||
myDaemonAnalyzer = new ProjectStructureDaemonAnalyzer(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Set<String> getCachedDependencies(final Object selectedObject, boolean force) {
|
||||
if (selectedObject instanceof Library){
|
||||
final Library library = (Library)selectedObject;
|
||||
if (myLibraryDependencyCache.containsKey(library)){
|
||||
return myLibraryDependencyCache.get(library);
|
||||
}
|
||||
} else if (selectedObject instanceof Sdk){
|
||||
final Sdk projectJdk = (Sdk)selectedObject;
|
||||
if (myJdkDependencyCache.containsKey(projectJdk)){
|
||||
return myJdkDependencyCache.get(projectJdk);
|
||||
}
|
||||
} else if (selectedObject instanceof Module) {
|
||||
final Module module = (Module)selectedObject;
|
||||
if (myModulesDependencyCache.containsKey(module)) {
|
||||
return myModulesDependencyCache.get(module);
|
||||
}
|
||||
}
|
||||
if (force){
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isDispatchThread());
|
||||
final Set<String> dep = getDependencies(selectedObject);
|
||||
updateCache(selectedObject, dep);
|
||||
return dep;
|
||||
} else {
|
||||
myUpdateDependenciesAlarm.addRequest(new Runnable(){
|
||||
public void run() {
|
||||
final Set<String> dep = getDependencies(selectedObject);
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (!myDisposed) {
|
||||
updateCache(selectedObject, dep);
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
return null;
|
||||
}
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
private void updateCache(final Object selectedObject, final Set<String> dep) {
|
||||
if (selectedObject instanceof Library) {
|
||||
myLibraryDependencyCache.put((Library)selectedObject, dep);
|
||||
}
|
||||
else if (selectedObject instanceof Sdk) {
|
||||
myJdkDependencyCache.put((Sdk)selectedObject, dep);
|
||||
}
|
||||
else if (selectedObject instanceof Module) {
|
||||
myModulesDependencyCache.put((Module)selectedObject, dep);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> getDependencies(final Condition<OrderEntry> condition) {
|
||||
final Set<String> result = new TreeSet<String>();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Module[] modules = myModulesConfigurator.getModules();
|
||||
for (final Module module : modules) {
|
||||
final ModuleEditor moduleEditor = myModulesConfigurator.getModuleEditor(module);
|
||||
if (moduleEditor != null) {
|
||||
final OrderEntry[] entries = moduleEditor.getOrderEntries();
|
||||
for (OrderEntry entry : entries) {
|
||||
if (myDisposed) return;
|
||||
if (condition.value(entry)) {
|
||||
result.add(module.getName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Set<String> getDependencies(final Object selectedObject) {
|
||||
if (selectedObject instanceof Module) {
|
||||
return getDependencies(new Condition<OrderEntry>() {
|
||||
public boolean value(final OrderEntry orderEntry) {
|
||||
return orderEntry instanceof ModuleOrderEntry && Comparing.equal(((ModuleOrderEntry)orderEntry).getModule(), selectedObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selectedObject instanceof Library) {
|
||||
Library library = (Library)selectedObject;
|
||||
if (library.getTable() == null) { //module library navigation
|
||||
HashSet<String> deps = new HashSet<String>();
|
||||
Module module = ((LibraryImpl)library).getModule();
|
||||
if (module != null) {
|
||||
deps.add(module.getName());
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
return getDependencies(new Condition<OrderEntry>() {
|
||||
@SuppressWarnings({"SimplifiableIfStatement"})
|
||||
public boolean value(final OrderEntry orderEntry) {
|
||||
if (orderEntry instanceof LibraryOrderEntry){
|
||||
final LibraryImpl library = (LibraryImpl)((LibraryOrderEntry)orderEntry).getLibrary();
|
||||
if (Comparing.equal(library, selectedObject)) return true;
|
||||
return library != null && Comparing.equal(library.getSource(), selectedObject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selectedObject instanceof Sdk) {
|
||||
return getDependencies(new Condition<OrderEntry>() {
|
||||
public boolean value(final OrderEntry orderEntry) {
|
||||
return orderEntry instanceof JdkOrderEntry && Comparing.equal(((JdkOrderEntry)orderEntry).getJdk(), selectedObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
public ProjectStructureDaemonAnalyzer getDaemonAnalyzer() {
|
||||
return myDaemonAnalyzer;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
clearCaches();
|
||||
myDisposed = true;
|
||||
}
|
||||
|
||||
public void invalidateModules(final Set<String> modules) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (modules != null) {
|
||||
for (String module : modules) {
|
||||
myValidityCache.remove(myModuleManager.findModuleByName(module));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
public void invalidateModuleName(final Module module) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
final Map<String, Set<String>> problems = myValidityCache.remove(module);
|
||||
if (problems != null) {
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ModulesConfigurator getModulesConfigurator() {
|
||||
return myModulesConfigurator;
|
||||
}
|
||||
|
||||
public void clearCaches() {
|
||||
myJdkDependencyCache.clear();
|
||||
myLibraryDependencyCache.clear();
|
||||
myValidityCache.clear();
|
||||
myLibraryPathValidityCache.clear();
|
||||
myModulesDependencyCache.clear();
|
||||
myCacheUpdaters.clear();
|
||||
}
|
||||
|
||||
public void clearCaches(final Module module, final List<Library> chosen) {
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isDispatchThread());
|
||||
for (Library library : chosen) {
|
||||
myLibraryDependencyCache.remove(library);
|
||||
}
|
||||
myValidityCache.remove(module);
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
|
||||
public void clearCaches(final Module module, final Sdk oldJdk, final Sdk selectedModuleJdk) {
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isDispatchThread());
|
||||
myJdkDependencyCache.remove(oldJdk);
|
||||
myJdkDependencyCache.remove(selectedModuleJdk);
|
||||
myValidityCache.remove(module);
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
|
||||
public void clearCaches(final OrderEntry entry) {
|
||||
LOG.assertTrue(ApplicationManager.getApplication().isDispatchThread());
|
||||
if (entry instanceof ModuleOrderEntry) {
|
||||
final Module module = ((ModuleOrderEntry)entry).getModule();
|
||||
myValidityCache.remove(module);
|
||||
myModulesDependencyCache.remove(module);
|
||||
} else if (entry instanceof JdkOrderEntry) {
|
||||
invalidateModules(myJdkDependencyCache.remove(((JdkOrderEntry)entry).getJdk()));
|
||||
} else if (entry instanceof LibraryOrderEntry) {
|
||||
invalidateModules(myLibraryDependencyCache.remove(((LibraryOrderEntry)entry).getLibrary()));
|
||||
}
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
|
||||
public ValidityLevel isInvalid(final Object object) {
|
||||
if (object instanceof Module){
|
||||
final Module module = (Module)object;
|
||||
if (myValidityCache.containsKey(module)) {
|
||||
boolean valid = myValidityCache.get(module) == null;
|
||||
return valid ? ValidityLevel.VALID : ValidityLevel.ERROR;
|
||||
}
|
||||
myUpdateDependenciesAlarm.addRequest(new Runnable(){
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
updateModuleValidityCache(module);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
} else if (object instanceof LibraryEx) {
|
||||
final LibraryEx library = (LibraryEx)object;
|
||||
if (myLibraryPathValidityCache.containsKey(library)) return myLibraryPathValidityCache.get(library);
|
||||
myUpdateDependenciesAlarm.addRequest(new Runnable(){
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
updateLibraryValidityCache(library);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
return ValidityLevel.VALID;
|
||||
}
|
||||
|
||||
private void updateLibraryValidityCache(final LibraryEx library) {
|
||||
if (myLibraryPathValidityCache.containsKey(library)) return; //do not check twice
|
||||
ValidityLevel level = ValidityLevel.VALID;
|
||||
if (!(library.allPathsValid(JavadocOrderRootType.getInstance()) && library.allPathsValid(OrderRootType.SOURCES))) {
|
||||
level = ValidityLevel.WARNING;
|
||||
}
|
||||
if (!library.allPathsValid(OrderRootType.CLASSES)) {
|
||||
level = ValidityLevel.ERROR;
|
||||
}
|
||||
|
||||
final ValidityLevel finalLevel = level;
|
||||
SwingUtilities.invokeLater(new Runnable(){
|
||||
public void run() {
|
||||
if (!myDisposed){
|
||||
myLibraryPathValidityCache.put(library, finalLevel);
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateModuleValidityCache(final Module module) {
|
||||
if (myValidityCache.containsKey(module)) return; //do not check twice
|
||||
|
||||
if (myDisposed) return;
|
||||
|
||||
Map<String, Set<String>> problems = null;
|
||||
final ModifiableModuleModel moduleModel = myModulesConfigurator.getModuleModel();
|
||||
final Module[] all = moduleModel.getModules();
|
||||
for (Module each : all) {
|
||||
if (each != module && getRealName(each).equals(getRealName(module))) {
|
||||
problems = new HashMap<String, Set<String>>();
|
||||
problems.put(DUPLICATE_MODULE_NAME, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final ModuleRootModel rootModel = myModulesConfigurator.getRootModel(module);
|
||||
if (rootModel == null) return; //already disposed
|
||||
final OrderEntry[] entries = rootModel.getOrderEntries();
|
||||
for (OrderEntry entry : entries) {
|
||||
if (myDisposed) return;
|
||||
if (!entry.isValid()){
|
||||
if (problems == null) {
|
||||
problems = new HashMap<String, Set<String>>();
|
||||
}
|
||||
if (entry instanceof JdkOrderEntry && ((JdkOrderEntry)entry).getJdkName() == null) {
|
||||
problems.put(NO_JDK, null);
|
||||
} else {
|
||||
Set<String> deletedLibraries = problems.get(DELETED_LIBRARIES);
|
||||
if (deletedLibraries == null){
|
||||
deletedLibraries = new HashSet<String>();
|
||||
problems.put(DELETED_LIBRARIES, deletedLibraries);
|
||||
}
|
||||
deletedLibraries.add(entry.getPresentableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
final Map<String, Set<String>> finalProblems = problems;
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (!myDisposed) {
|
||||
myValidityCache.put(module, finalProblems);
|
||||
fireOnCacheChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Module[] getModules() {
|
||||
return myModulesConfigurator.getModules();
|
||||
}
|
||||
@@ -382,38 +75,6 @@ public class StructureConfigurableContext implements Disposable {
|
||||
return newName != null ? newName : module.getName();
|
||||
}
|
||||
|
||||
public boolean isUnused(final Object object) {
|
||||
if (object == null) return false;
|
||||
if (object instanceof Module){
|
||||
getCachedDependencies(object, false);
|
||||
return false;
|
||||
}
|
||||
if (object instanceof Sdk) {
|
||||
return false;
|
||||
}
|
||||
if (object instanceof Library) {
|
||||
final LibraryTable libraryTable = ((Library)object).getTable();
|
||||
if (libraryTable == null || !libraryTable.getTableLevel().equals(LibraryTablesRegistrar.PROJECT_LEVEL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final Set<String> dependencies = getCachedDependencies(object, false);
|
||||
return dependencies != null && dependencies.isEmpty();
|
||||
}
|
||||
|
||||
private void fireOnCacheChanged() {
|
||||
final Runnable[] all = myCacheUpdaters.toArray(new Runnable[myCacheUpdaters.size()]);
|
||||
for (Runnable each : all) {
|
||||
each.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void addReloadProjectRequest(final Runnable runnable) {
|
||||
myReloadProjectAlarm.cancelAllRequests();
|
||||
myReloadProjectAlarm.addRequest(runnable, 300, ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
|
||||
public void resetLibraries() {
|
||||
final LibraryTablesRegistrar tablesRegistrar = LibraryTablesRegistrar.getInstance();
|
||||
|
||||
@@ -488,12 +149,8 @@ public class StructureConfigurableContext implements Disposable {
|
||||
|
||||
|
||||
public void reset() {
|
||||
myDisposed = false;
|
||||
myDaemonAnalyzer.reset();
|
||||
resetLibraries();
|
||||
myModulesConfigurator.resetModuleEditors();
|
||||
}
|
||||
|
||||
public void addCacheUpdateListener(Runnable runnable) {
|
||||
myCacheUpdaters.add(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.roots.JavadocOrderRootType;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
|
||||
import com.intellij.openapi.roots.impl.libraries.LibraryImpl;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class LibraryProjectStructureElement extends ProjectStructureElement {
|
||||
private final Library myLibrary;
|
||||
|
||||
public LibraryProjectStructureElement(@NotNull StructureConfigurableContext context, @NotNull Library library) {
|
||||
super(context);
|
||||
myLibrary = library;
|
||||
}
|
||||
|
||||
public Library getLibrary() {
|
||||
return myLibrary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(ProjectStructureProblemsHolder problemsHolder) {
|
||||
final LibraryEx library = (LibraryEx)myLibrary;
|
||||
final String libraryName = myLibrary.getName();//todo[nik] get modified name?
|
||||
if (!library.allPathsValid(OrderRootType.CLASSES)) {
|
||||
problemsHolder.addError(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
|
||||
}
|
||||
else if (!library.allPathsValid(JavadocOrderRootType.getInstance()) || !library.allPathsValid(OrderRootType.SOURCES)) {
|
||||
problemsHolder.addWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProjectStructureElementUsage> getUsagesInElement() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof LibraryProjectStructureElement)) return false;
|
||||
|
||||
return getSourceOrThis().equals(((LibraryProjectStructureElement)o).getSourceOrThis());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Library getSourceOrThis() {
|
||||
final Library source = ((LibraryImpl)myLibrary).getSource();
|
||||
return source != null ? source : myLibrary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getSourceOrThis().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "library:" + myLibrary.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean highlightIfUnused() {
|
||||
final LibraryTable libraryTable = myLibrary.getTable();
|
||||
return libraryTable != null && LibraryTablesRegistrar.PROJECT_LEVEL.equals(libraryTable.getTableLevel());
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.ProjectBundle;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModuleEditor;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ModuleProjectStructureElement extends ProjectStructureElement {
|
||||
private Module myModule;
|
||||
|
||||
public ModuleProjectStructureElement(@NotNull StructureConfigurableContext context, @NotNull Module module) {
|
||||
super(context);
|
||||
myModule = module;
|
||||
}
|
||||
|
||||
public Module getModule() {
|
||||
return myModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(ProjectStructureProblemsHolder problemsHolder) {
|
||||
final ModifiableModuleModel moduleModel = myContext.getModulesConfigurator().getModuleModel();
|
||||
final Module[] all = moduleModel.getModules();
|
||||
for (Module each : all) {
|
||||
if (each != myModule && myContext.getRealName(each).equals(myContext.getRealName(myModule))) {
|
||||
problemsHolder.addError(ProjectBundle.message("project.roots.module.duplicate.name.message"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final ModuleRootModel rootModel = myContext.getModulesConfigurator().getRootModel(myModule);
|
||||
if (rootModel == null) return; //already disposed
|
||||
final OrderEntry[] entries = rootModel.getOrderEntries();
|
||||
for (OrderEntry entry : entries) {
|
||||
if (!entry.isValid()){
|
||||
if (entry instanceof JdkOrderEntry && ((JdkOrderEntry)entry).getJdkName() == null) {
|
||||
problemsHolder.addError(ProjectBundle.message("project.roots.module.jdk.problem.message"));
|
||||
} else {
|
||||
problemsHolder.addError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProjectStructureElementUsage> getUsagesInElement() {
|
||||
final List<ProjectStructureElementUsage> usages = new ArrayList<ProjectStructureElementUsage>();
|
||||
final ModuleEditor moduleEditor = myContext.getModulesConfigurator().getModuleEditor(myModule);
|
||||
if (moduleEditor != null) {
|
||||
for (OrderEntry entry : moduleEditor.getOrderEntries()) {
|
||||
if (entry instanceof ModuleOrderEntry) {
|
||||
final Module module = ((ModuleOrderEntry)entry).getModule();
|
||||
if (module != null) {
|
||||
usages.add(new UsageInModuleClasspath(myContext, this, new ModuleProjectStructureElement(myContext, module)));
|
||||
}
|
||||
}
|
||||
else if (entry instanceof LibraryOrderEntry) {
|
||||
final Library library = ((LibraryOrderEntry)entry).getLibrary();
|
||||
if (library != null) {
|
||||
usages.add(new UsageInModuleClasspath(myContext, this, new LibraryProjectStructureElement(myContext, library)));
|
||||
}
|
||||
}
|
||||
else if (entry instanceof JdkOrderEntry) {
|
||||
final Sdk jdk = ((JdkOrderEntry)entry).getJdk();
|
||||
if (jdk != null) {
|
||||
usages.add(new UsageInModuleClasspath(myContext, this, new SdkProjectStructureElement(myContext, jdk)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return usages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof ModuleProjectStructureElement)) return false;
|
||||
|
||||
return myModule.equals(((ModuleProjectStructureElement)o).myModule);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myModule.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "module:" + myModule.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean highlightIfUnused() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+243
@@ -0,0 +1,243 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.MultiValuesMap;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ProjectStructureDaemonAnalyzer implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.ui.configuration.projectRoot.validation.ProjectStructureDaemonAnalyzer");
|
||||
private Map<ProjectStructureElement, ProjectStructureProblemsHolder> myProblemHolders = new HashMap<ProjectStructureElement, ProjectStructureProblemsHolder>();
|
||||
private MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage> mySourceElement2Usages = new MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage>();
|
||||
private MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage> myContainingElement2Usages = new MultiValuesMap<ProjectStructureElement, ProjectStructureElementUsage>();
|
||||
private Set<ProjectStructureElement> myElementWithNotCalculatedUsages = new HashSet<ProjectStructureElement>();
|
||||
private MergingUpdateQueue myAnalyzerQueue;
|
||||
private List<Runnable> myListeners = new ArrayList<Runnable>();
|
||||
private boolean myDisposed;
|
||||
|
||||
public ProjectStructureDaemonAnalyzer(StructureConfigurableContext context) {
|
||||
Disposer.register(context, this);
|
||||
myAnalyzerQueue = new MergingUpdateQueue("Project Structure Daemon Analyzer", 300, false, null, this, null, false);
|
||||
}
|
||||
|
||||
private void doUpdate(final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
|
||||
if (myDisposed) return;
|
||||
|
||||
if (check) {
|
||||
doCheck(element);
|
||||
}
|
||||
if (collectUsages) {
|
||||
doCollectUsages(element);
|
||||
}
|
||||
}
|
||||
|
||||
private void doCheck(final ProjectStructureElement element) {
|
||||
final ProjectStructureProblemsHolder problemsHolder = new ProjectStructureProblemsHolder();
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("checking " + element);
|
||||
}
|
||||
element.check(problemsHolder);
|
||||
}
|
||||
}.execute();
|
||||
invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("updating problems for " + element);
|
||||
}
|
||||
myProblemHolders.put(element, problemsHolder);
|
||||
fireProblemsUpdated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void fireProblemsUpdated() {
|
||||
Runnable[] listeners = myListeners.toArray(new Runnable[myListeners.size()]);
|
||||
for (Runnable listener : listeners) {
|
||||
listener.run();
|
||||
}
|
||||
}
|
||||
|
||||
private void doCollectUsages(final ProjectStructureElement element) {
|
||||
final List<ProjectStructureElementUsage> usages = new ReadAction<List<ProjectStructureElementUsage>>() {
|
||||
protected void run(final Result<List<ProjectStructureElementUsage>> result) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("collecting usages in " + element);
|
||||
}
|
||||
result.setResult(element.getUsagesInElement());
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
|
||||
invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("updating usages for " + element);
|
||||
}
|
||||
updateUsages(element, usages);
|
||||
fireProblemsUpdated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUsages(ProjectStructureElement element, List<ProjectStructureElementUsage> usages) {
|
||||
removeUsagesInElement(element);
|
||||
for (ProjectStructureElementUsage usage : usages) {
|
||||
addUsage(usage);
|
||||
}
|
||||
myElementWithNotCalculatedUsages.remove(element);
|
||||
}
|
||||
|
||||
private static void invokeLater(Runnable runnable) {
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
|
||||
public void queueUpdate(@NotNull final ProjectStructureElement element) {
|
||||
queueUpdate(element, true, true);
|
||||
}
|
||||
|
||||
public void queueUpdate(@NotNull final ProjectStructureElement element, final boolean check, final boolean collectUsages) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("start " + (check ? "checking " : "") + (collectUsages ? "collecting usages " : "") + "for " + element);
|
||||
}
|
||||
if (collectUsages) {
|
||||
myElementWithNotCalculatedUsages.add(element);
|
||||
}
|
||||
myAnalyzerQueue.queue(new AnalyzeElementUpdate(element, check, collectUsages));
|
||||
}
|
||||
|
||||
public void removeElement(ProjectStructureElement element) {
|
||||
myElementWithNotCalculatedUsages.remove(element);
|
||||
myProblemHolders.remove(element);
|
||||
final Collection<ProjectStructureElementUsage> usages = mySourceElement2Usages.removeAll(element);
|
||||
if (usages != null) {
|
||||
for (ProjectStructureElementUsage usage : usages) {
|
||||
myProblemHolders.remove(usage.getContainingElement());
|
||||
}
|
||||
}
|
||||
removeUsagesInElement(element);
|
||||
fireProblemsUpdated();
|
||||
}
|
||||
|
||||
public boolean isUnused(ProjectStructureElement element) {
|
||||
if (!element.highlightIfUnused()) {
|
||||
return false;
|
||||
}
|
||||
if (!myElementWithNotCalculatedUsages.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final Collection<ProjectStructureElementUsage> usages = mySourceElement2Usages.get(element);
|
||||
return usages == null || usages.isEmpty();
|
||||
}
|
||||
|
||||
private void removeUsagesInElement(ProjectStructureElement element) {
|
||||
final Collection<ProjectStructureElementUsage> usages = myContainingElement2Usages.removeAll(element);
|
||||
if (usages != null) {
|
||||
for (ProjectStructureElementUsage usage : usages) {
|
||||
mySourceElement2Usages.remove(usage.getSourceElement(), usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addUsage(@NotNull ProjectStructureElementUsage usage) {
|
||||
mySourceElement2Usages.put(usage.getSourceElement(), usage);
|
||||
myContainingElement2Usages.put(usage.getContainingElement(), usage);
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
LOG.debug("analyzer stopped");
|
||||
myAnalyzerQueue.cancelAllUpdates();
|
||||
clearCaches();
|
||||
myAnalyzerQueue.deactivate();
|
||||
}
|
||||
|
||||
public void clearCaches() {
|
||||
LOG.debug("clear caches");
|
||||
myProblemHolders.clear();
|
||||
mySourceElement2Usages.clear();
|
||||
myContainingElement2Usages.clear();
|
||||
myElementWithNotCalculatedUsages.clear();
|
||||
}
|
||||
|
||||
public void clearAllProblems() {
|
||||
myProblemHolders.clear();
|
||||
fireProblemsUpdated();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myDisposed = true;
|
||||
myAnalyzerQueue.cancelAllUpdates();
|
||||
}
|
||||
|
||||
public ProjectStructureProblemsHolder getProblemsHolder(ProjectStructureElement element) {
|
||||
return myProblemHolders.get(element);
|
||||
}
|
||||
|
||||
public Collection<ProjectStructureElementUsage> getUsages(ProjectStructureElement selected) {
|
||||
ProjectStructureElement[] elements = myElementWithNotCalculatedUsages.toArray(new ProjectStructureElement[myElementWithNotCalculatedUsages.size()]);
|
||||
for (ProjectStructureElement element : elements) {
|
||||
updateUsages(element, element.getUsagesInElement());
|
||||
}
|
||||
fireProblemsUpdated();
|
||||
final Collection<ProjectStructureElementUsage> usages = mySourceElement2Usages.get(selected);
|
||||
return usages != null ? usages : Collections.<ProjectStructureElementUsage>emptyList();
|
||||
}
|
||||
|
||||
public void addListener(Runnable runnable) {
|
||||
LOG.debug("listener added " + runnable);
|
||||
myListeners.add(runnable);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
LOG.debug("analyzer started");
|
||||
myAnalyzerQueue.activate();
|
||||
myAnalyzerQueue.queue(new Update("reset") {
|
||||
public void run() {
|
||||
myDisposed = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class AnalyzeElementUpdate extends Update {
|
||||
private final ProjectStructureElement myElement;
|
||||
private final boolean myCheck;
|
||||
private final boolean myCollectUsages;
|
||||
private final Object[] myEqualityObjects;
|
||||
|
||||
public AnalyzeElementUpdate(ProjectStructureElement element, boolean check, boolean collectUsages) {
|
||||
super(element);
|
||||
myElement = element;
|
||||
myCheck = check;
|
||||
myCollectUsages = collectUsages;
|
||||
myEqualityObjects = new Object[]{myElement, myCheck, myCollectUsages};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(Update update) {
|
||||
if (!(update instanceof AnalyzeElementUpdate)) return false;
|
||||
final AnalyzeElementUpdate other = (AnalyzeElementUpdate)update;
|
||||
return myElement.equals(other.myElement) && (!other.myCheck || myCheck) && (!other.myCollectUsages || myCollectUsages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getEqualityObjects() {
|
||||
return myEqualityObjects;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
doUpdate(myElement, myCheck, myCollectUsages);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectStructureElement {
|
||||
protected final StructureConfigurableContext myContext;
|
||||
|
||||
protected ProjectStructureElement(@NotNull StructureConfigurableContext context) {
|
||||
myContext = context;
|
||||
}
|
||||
|
||||
public abstract void check(ProjectStructureProblemsHolder problemsHolder);
|
||||
|
||||
public abstract List<ProjectStructureElementUsage> getUsagesInElement();
|
||||
|
||||
public abstract boolean highlightIfUnused();
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectStructureElementUsage {
|
||||
public abstract ProjectStructureElement getSourceElement();
|
||||
|
||||
public abstract ProjectStructureElement getContainingElement();
|
||||
|
||||
public abstract String getPresentableName();
|
||||
|
||||
public abstract void navigate();
|
||||
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
public abstract Icon getIcon();
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.daemon;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ProjectStructureProblemDescription {
|
||||
private String myMessage;
|
||||
private final Severity mySeverity;
|
||||
|
||||
public ProjectStructureProblemDescription(String message, Severity severity) {
|
||||
myMessage = message;
|
||||
mySeverity = severity;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return myMessage;
|
||||
}
|
||||
|
||||
public Severity getSeverity() {
|
||||
return mySeverity;
|
||||
}
|
||||
|
||||
public enum Severity { ERROR, WARNING }
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.StringBuilderSpinAllocator;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ProjectStructureProblemsHolder {
|
||||
private List<ProjectStructureProblemDescription> myProblemDescriptions;
|
||||
|
||||
public void addError(String message) {
|
||||
addProblem(message, ProjectStructureProblemDescription.Severity.ERROR);
|
||||
}
|
||||
|
||||
public void addWarning(String message) {
|
||||
addProblem(message, ProjectStructureProblemDescription.Severity.WARNING);
|
||||
}
|
||||
|
||||
public void addProblem(String description, ProjectStructureProblemDescription.Severity severity) {
|
||||
if (myProblemDescriptions == null) {
|
||||
myProblemDescriptions = new SmartList<ProjectStructureProblemDescription>();
|
||||
}
|
||||
myProblemDescriptions.add(new ProjectStructureProblemDescription(description, severity));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ProjectStructureProblemDescription.Severity getSeverity() {
|
||||
if (myProblemDescriptions == null || myProblemDescriptions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (ProjectStructureProblemDescription description : myProblemDescriptions) {
|
||||
if (description.getSeverity() == ProjectStructureProblemDescription.Severity.ERROR) {
|
||||
return ProjectStructureProblemDescription.Severity.ERROR;
|
||||
}
|
||||
}
|
||||
return ProjectStructureProblemDescription.Severity.WARNING;
|
||||
}
|
||||
|
||||
public String composeTooltipMessage() {
|
||||
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
|
||||
try {
|
||||
if (myProblemDescriptions != null) {
|
||||
for (ProjectStructureProblemDescription problemDescription : myProblemDescriptions) {
|
||||
buf.append(problemDescription.getMessage()).append("\n");
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
finally {
|
||||
StringBuilderSpinAllocator.dispose(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class SdkProjectStructureElement extends ProjectStructureElement {
|
||||
private Sdk mySdk;
|
||||
|
||||
public SdkProjectStructureElement(StructureConfigurableContext context, Sdk sdk) {
|
||||
super(context);
|
||||
mySdk = sdk;
|
||||
}
|
||||
|
||||
public Sdk getSdk() {
|
||||
return mySdk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(ProjectStructureProblemsHolder problemsHolder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProjectStructureElementUsage> getUsagesInElement() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof SdkProjectStructureElement)) return false;
|
||||
return mySdk.equals(((SdkProjectStructureElement)o).mySdk);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mySdk.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "sdk:" + mySdk.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean highlightIfUnused() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.impl.OrderEntryUtil;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.ModuleStructureConfigurable;
|
||||
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class UsageInModuleClasspath extends ProjectStructureElementUsage {
|
||||
private final StructureConfigurableContext myContext;
|
||||
private final ModuleProjectStructureElement myContainingElement;
|
||||
private ProjectStructureElement mySourceElement;
|
||||
private Module myModule;
|
||||
|
||||
public UsageInModuleClasspath(@NotNull StructureConfigurableContext context, @NotNull ModuleProjectStructureElement containingElement, ProjectStructureElement sourceElement) {
|
||||
myContext = context;
|
||||
myContainingElement = containingElement;
|
||||
myModule = containingElement.getModule();
|
||||
mySourceElement = sourceElement;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getSourceElement() {
|
||||
return mySourceElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectStructureElement getContainingElement() {
|
||||
return myContainingElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
return myModule.getName();
|
||||
}
|
||||
|
||||
public String getModuleName() {
|
||||
return myModule.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate() {
|
||||
ModulesConfigurator modulesConfigurator = myContext.getModulesConfigurator();
|
||||
|
||||
ModuleRootModel rootModel = modulesConfigurator.getRootModel(myModule);
|
||||
OrderEntry entry;
|
||||
if (mySourceElement instanceof LibraryProjectStructureElement) {
|
||||
entry = OrderEntryUtil.findLibraryOrderEntry(rootModel, ((LibraryProjectStructureElement)mySourceElement).getLibrary());
|
||||
}
|
||||
else if (mySourceElement instanceof ModuleProjectStructureElement) {
|
||||
entry = OrderEntryUtil.findModuleOrderEntry(rootModel, ((ModuleProjectStructureElement)mySourceElement).getModule());
|
||||
}
|
||||
else if (mySourceElement instanceof SdkProjectStructureElement) {
|
||||
entry = OrderEntryUtil.findJdkOrderEntry(rootModel, ((SdkProjectStructureElement)mySourceElement).getSdk());
|
||||
}
|
||||
else {
|
||||
entry = null;
|
||||
}
|
||||
ModuleStructureConfigurable.getInstance(myContext.getProject()).selectOrderEntry(myModule, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myModule.hashCode()*31 + mySourceElement.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof UsageInModuleClasspath && myModule.equals(((UsageInModuleClasspath)obj).myModule)
|
||||
&& mySourceElement.equals(((UsageInModuleClasspath)obj).mySourceElement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return myModule.getModuleType().getNodeIcon(false);
|
||||
}
|
||||
}
|
||||
@@ -461,14 +461,14 @@ public abstract class MasterDetailsComponent implements Configurable, Persistent
|
||||
}
|
||||
|
||||
public void fireItemsChangeListener(final Object editableObject) {
|
||||
for (ItemsChangeListener listner : myListners) {
|
||||
listner.itemChanged(editableObject);
|
||||
for (ItemsChangeListener listener : myListners) {
|
||||
listener.itemChanged(editableObject);
|
||||
}
|
||||
}
|
||||
|
||||
private void fireItemsChangedExternally() {
|
||||
for (ItemsChangeListener listner : myListners) {
|
||||
listner.itemsExternallyChanged();
|
||||
for (ItemsChangeListener listener : myListners) {
|
||||
listener.itemsExternallyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ choose.modules.dialog.title=Choose modules
|
||||
choose.modules.dialog.description=<html>Library '' {0}'' will be added to the selected modules.</html>
|
||||
project.roots.module.jdk.problem.message=Module JDK is not defined.
|
||||
project.roots.module.duplicate.name.message=Duplicate module name
|
||||
project.roots.library.problem.message=Classpath {0, choice, 1#entry is invalid: |2#entries are invalid: \n}
|
||||
project.roots.library.problem.message=Classpath entry is invalid: {0}
|
||||
project.roots.project.display.name=Project
|
||||
project.roots.global.resources.display.name=Global Resources
|
||||
project.roots.modules.display.name=Modules
|
||||
|
||||
Reference in New Issue
Block a user