diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index 50b6a4bbf64c..57605dbe1969 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -80,6 +80,9 @@ org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper + + org.jetbrains.plugins.gradle.util.GradleProjectStructureContext + org.jetbrains.plugins.gradle.importing.GradleLocalNodeImportHelper diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java index 7cc983906126..146fa370e035 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java @@ -9,10 +9,8 @@ import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.gradle.diff.PlatformFacade; -import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; -import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.ui.RichTextControlBuilder; +import org.jetbrains.plugins.gradle.util.GradleBundle; import javax.swing.*; import java.awt.*; @@ -44,25 +42,15 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel { private final JPanel myContent = new JPanel(myLayout); private final Project myProject; - private final PlatformFacade myProjectFacade; - private final GradleProjectStructureHelper myProjectStructureHelper; - - protected GradleToolWindowPanel(@NotNull Project project, - @Nullable PlatformFacade projectFacade, - @NotNull GradleProjectStructureHelper projectStructureHelper, - @NotNull String place) - { + + protected GradleToolWindowPanel(@NotNull Project project, @NotNull String place) { super(true); myProject = project; - myProjectFacade = projectFacade; - myProjectStructureHelper = projectStructureHelper; final ActionManager actionManager = ActionManager.getInstance(); final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(TOOL_WINDOW_TOOLBAR_ID); ActionToolbar actionToolbar = actionManager.createActionToolbar(place, actionGroup, true); setToolbar(actionToolbar.getComponent()); - initContent(); setContent(myContent); - update(); MessageBusConnection connection = project.getMessageBus().connect(project); connection.subscribe(GradleConfigNotifier.TOPIC, new GradleConfigNotifier() { @@ -73,7 +61,7 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel { }); } - private void initContent() { + public void initContent() { final JComponent payloadControl = buildContent(); myContent.add(ScrollPaneFactory.createScrollPane(payloadControl), CONTENT_CARD_NAME); RichTextControlBuilder builder = new RichTextControlBuilder(); @@ -83,6 +71,7 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel { builder.setText(GradleBundle.message("gradle.toolwindow.text.no.linked.project")); final JComponent noLinkedProjectControl = builder.build(); myContent.add(noLinkedProjectControl, NON_LINKED_CARD_NAME); + update(); } /** @@ -101,16 +90,6 @@ public abstract class GradleToolWindowPanel extends SimpleToolWindowPanel { return myProject; } - @NotNull - public PlatformFacade getProjectFacade() { - return myProjectFacade; - } - - @NotNull - public GradleProjectStructureHelper getProjectStructureHelper() { - return myProjectStructureHelper; - } - /** * @return GUI control to be displayed at the current tab */ diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java index 16ee64b7690f..a70baef647d3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java @@ -8,6 +8,7 @@ import com.intellij.openapi.roots.OrderEntry; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.gradle.*; import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; import org.jetbrains.plugins.gradle.util.GradleUtil; import java.util.HashMap; @@ -90,11 +91,19 @@ public class GradleDiffUtil { @Override public void visit(@NotNull Module module) { context.register(new GradleModulePresenceChange(null, module)); + for (ModuleAwareContentRoot contentRoot : context.getPlatformFacade().getContentRoots(module)) { + visit(contentRoot); + } for (OrderEntry entry : context.getPlatformFacade().getOrderEntries(module)) { GradleUtil.dispatch(entry, this); } } + @Override + public void visit(@NotNull ModuleAwareContentRoot contentRoot) { + // TODO den implement + } + @Override public void visit(@NotNull LibraryOrderEntry libraryDependency) { final String libraryName = libraryDependency.getLibraryName(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java index 042fae1757d5..4dcd8b0b4d62 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java @@ -7,6 +7,7 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; import java.util.Collection; @@ -36,7 +37,10 @@ public interface PlatformFacade { @NotNull Collection getModules(@NotNull Project project); - + + @NotNull + Collection getContentRoots(@NotNull Module module); + @NotNull Collection getOrderEntries(@NotNull Module module); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java index 587ffa7c7500..6399ca744c4b 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java @@ -4,6 +4,7 @@ import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderEntry; @@ -12,10 +13,14 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; /** * @author Denis Zhdanov @@ -41,6 +46,21 @@ public class PlatformFacadeImpl implements PlatformFacade { return Arrays.asList(ModuleManager.getInstance(project).getModules()); } + @NotNull + @Override + public Collection getContentRoots(@NotNull final Module module) { + final ContentEntry[] entries = ModuleRootManager.getInstance(module).getContentEntries(); + if (entries == null) { + return Collections.emptyList(); + } + return ContainerUtil.map(entries, new Function() { + @Override + public ModuleAwareContentRoot fun(ContentEntry entry) { + return new ModuleAwareContentRoot(module, entry); + } + }); + } + @NotNull @Override public Collection getOrderEntries(@NotNull Module module) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleContentRootId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleContentRootId.java index e73b70937e44..918c8167ad03 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleContentRootId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleContentRootId.java @@ -5,6 +5,7 @@ import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; import org.jetbrains.plugins.gradle.model.gradle.GradleContentRoot; import org.jetbrains.plugins.gradle.model.gradle.GradleModule; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -21,8 +22,13 @@ public class GradleContentRootId extends GradleAbstractEntityId { myRootPath = rootPath; } + @NotNull + public String getRootPath() { + return myRootPath; + } + @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: final GradleModule module = context.getProjectStructureHelper().findGradleModule(myModuleName); @@ -39,4 +45,29 @@ public class GradleContentRootId extends GradleAbstractEntityId { } return null; } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + myModuleName.hashCode(); + result = 31 * result + myRootPath.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (!super.equals(o)) return false; + + GradleContentRootId that = (GradleContentRootId)o; + + if (!myModuleName.equals(that.myModuleName)) return false; + if (!myRootPath.equals(that.myRootPath)) return false; + + return true; + } + + @Override + public String toString() { + return "content root '" + myRootPath + "'"; + } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityId.java index 284b3680e50d..8184f2ce6a17 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityId.java @@ -4,9 +4,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** - * Represent unique identifier object for any gralde or intellij project structure entity (module, library, library dependency etc). + * Represent unique identifier object for any gradle or intellij project structure entity (module, library, library dependency etc). *

* We need an entity id, for example, at the 'sync project structure' tree - the model needs to keep mappings * between the existing tree nodes and corresponding project structure entities. However, we can't keep the entity as is because @@ -28,5 +29,5 @@ public interface GradleEntityId { void setOwner(@NotNull GradleEntityOwner owner); @Nullable - Object mapToEntity(@NotNull GradleEntityMappingContext context); + Object mapToEntity(@NotNull GradleProjectStructureContext context); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityIdMapper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityIdMapper.java index 7e5c93141ff4..d9d7ad393b83 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityIdMapper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityIdMapper.java @@ -10,8 +10,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.gradle.*; import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor; -import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; -import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; import org.jetbrains.plugins.gradle.util.GradleUtil; /** @@ -26,12 +26,10 @@ import org.jetbrains.plugins.gradle.util.GradleUtil; */ public class GradleEntityIdMapper { - @NotNull GradleEntityMappingContext myMappingContext; + @NotNull GradleProjectStructureContext myMappingContext; - public GradleEntityIdMapper(@NotNull GradleProjectStructureHelper projectStructureHelper, - @NotNull GradleProjectStructureChangesModel changesModel) - { - myMappingContext = new GradleEntityMappingContext(projectStructureHelper, changesModel); + public GradleEntityIdMapper(@NotNull GradleProjectStructureContext context) { + myMappingContext = context; } /** @@ -91,6 +89,11 @@ public class GradleEntityIdMapper { result.set(new GradleModuleId(GradleEntityOwner.INTELLIJ, module.getName())); } + @Override + public void visit(@NotNull ModuleAwareContentRoot contentRoot) { + result.set(new GradleContentRootId(GradleEntityOwner.INTELLIJ, contentRoot.getModule().getName(), contentRoot.getUrl())); + } + @Override public void visit(@NotNull LibraryOrderEntry libraryDependency) { final String libraryName = libraryDependency.getLibraryName(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryDependencyId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryDependencyId.java index 6ad1b6187bdc..f799606a2af0 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryDependencyId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryDependencyId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -15,7 +16,7 @@ public class GradleLibraryDependencyId extends GradleAbstractDependencyId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: return context.getProjectStructureHelper().findGradleLibraryDependency(getOwnerModuleName(), getDependencyName()); case INTELLIJ: return context.getProjectStructureHelper().findIntellijLibraryDependency(getOwnerModuleName(), getDependencyName()); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryId.java index 803262104548..248539a07717 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleLibraryId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -18,7 +19,7 @@ public class GradleLibraryId extends GradleAbstractEntityId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: return context.getProjectStructureHelper().findGradleLibrary(myLibraryName); case INTELLIJ: return context.getProjectStructureHelper().findIntellijLibrary(myLibraryName); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleDependencyId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleDependencyId.java index 342962b324a5..8182b8717b71 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleDependencyId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleDependencyId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -15,7 +16,7 @@ public class GradleModuleDependencyId extends GradleAbstractDependencyId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: return context.getProjectStructureHelper().findGradleModuleDependency(getOwnerModuleName(), getDependencyName()); case INTELLIJ: return context.getProjectStructureHelper().findIntellijModuleDependency(getOwnerModuleName(), getDependencyName()); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleId.java index 275887045ed8..65ffe7fe79c4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleModuleId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -18,7 +19,7 @@ public class GradleModuleId extends GradleAbstractEntityId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: return context.getProjectStructureHelper().findGradleModule(myModuleName); case INTELLIJ: return context.getProjectStructureHelper().findIntellijModule(myModuleName); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleProjectId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleProjectId.java index 1f1e869dd5e9..f1ddf43d7704 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleProjectId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleProjectId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * @author Denis Zhdanov @@ -15,7 +16,7 @@ public class GradleProjectId extends GradleAbstractEntityId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { switch (getOwner()) { case GRADLE: return context.getChangesModel().getGradleProject(); case INTELLIJ: return context.getProjectStructureHelper().getProject(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleSyntheticId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleSyntheticId.java index 1eb78d1fc595..2fb7aecd68ee 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleSyntheticId.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleSyntheticId.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.model.id; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.GradleEntityOwner; import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; /** * Whole 'entity id' thing is necessary for mapping 'sync project structures' tree nodes to the domain entities. However, there are @@ -30,7 +31,7 @@ public class GradleSyntheticId extends GradleAbstractEntityId { } @Override - public Object mapToEntity(@NotNull GradleEntityMappingContext context) { + public Object mapToEntity(@NotNull GradleProjectStructureContext context) { return null; } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitor.java index a2fb2843d196..cee80a11d1a5 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitor.java @@ -20,6 +20,8 @@ public interface IntellijEntityVisitor { void visit(@NotNull Module module); + void visit(@NotNull ModuleAwareContentRoot contentRoot); + void visit(@NotNull LibraryOrderEntry libraryDependency); void visit(@NotNull ModuleOrderEntry moduleDependency); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitorAdapter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitorAdapter.java deleted file mode 100644 index f0d7d2b7d851..000000000000 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/IntellijEntityVisitorAdapter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.jetbrains.plugins.gradle.model.intellij; - -import com.intellij.openapi.module.Module; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.LibraryOrderEntry; -import com.intellij.openapi.roots.ModuleOrderEntry; -import org.jetbrains.annotations.NotNull; - -/** - * @author Denis Zhdanov - * @since 2/14/12 1:51 PM - */ -public class IntellijEntityVisitorAdapter implements IntellijEntityVisitor { - @Override - public void visit(@NotNull Project project) { - } - @Override - public void visit(@NotNull Module module) { - } - @Override - public void visit(@NotNull LibraryOrderEntry libraryDependency) { - } - @Override - public void visit(@NotNull ModuleOrderEntry moduleDependency) { - } -} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/ModuleAwareContentRoot.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/ModuleAwareContentRoot.java new file mode 100644 index 000000000000..6ed115123607 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/intellij/ModuleAwareContentRoot.java @@ -0,0 +1,111 @@ +package org.jetbrains.plugins.gradle.model.intellij; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ExcludeFolder; +import com.intellij.openapi.roots.SourceFolder; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Denis Zhdanov + * @since 2/21/12 11:15 AM + */ +public class ModuleAwareContentRoot implements ContentEntry { + + @NotNull private final Module myModule; + @NotNull private final ContentEntry myDelegate; + + public ModuleAwareContentRoot(@NotNull Module module, @NotNull ContentEntry delegate) { + myDelegate = delegate; + myModule = module; + } + + @NotNull + public Module getModule() { + return myModule; + } + + @Override + @Nullable + public VirtualFile getFile() { + return myDelegate.getFile(); + } + + @Override + @NotNull + public String getUrl() { + return myDelegate.getUrl(); + } + + @Override + public SourceFolder[] getSourceFolders() { + return myDelegate.getSourceFolders(); + } + + @Override + public VirtualFile[] getSourceFolderFiles() { + return myDelegate.getSourceFolderFiles(); + } + + @Override + public ExcludeFolder[] getExcludeFolders() { + return myDelegate.getExcludeFolders(); + } + + @Override + public VirtualFile[] getExcludeFolderFiles() { + return myDelegate.getExcludeFolderFiles(); + } + + @Override + public SourceFolder addSourceFolder(@NotNull VirtualFile file, boolean isTestSource) { + return myDelegate.addSourceFolder(file, isTestSource); + } + + @Override + public SourceFolder addSourceFolder(@NotNull VirtualFile file, boolean isTestSource, @NotNull String packagePrefix) { + return myDelegate.addSourceFolder(file, isTestSource, packagePrefix); + } + + @Override + public SourceFolder addSourceFolder(@NotNull String url, boolean isTestSource) { + return myDelegate.addSourceFolder(url, isTestSource); + } + + @Override + public void removeSourceFolder(@NotNull SourceFolder sourceFolder) { + myDelegate.removeSourceFolder(sourceFolder); + } + + @Override + public void clearSourceFolders() { + myDelegate.clearSourceFolders(); + } + + @Override + public ExcludeFolder addExcludeFolder(@NotNull VirtualFile file) { + return myDelegate.addExcludeFolder(file); + } + + @Override + public ExcludeFolder addExcludeFolder(@NotNull String url) { + return myDelegate.addExcludeFolder(url); + } + + @Override + public void removeExcludeFolder(@NotNull ExcludeFolder excludeFolder) { + myDelegate.removeExcludeFolder(excludeFolder); + } + + @Override + public void clearExcludeFolders() { + myDelegate.clearExcludeFolders(); + } + + @Override + public boolean isSynthetic() { + return myDelegate.isSynthetic(); + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java index b21feae7cbcf..149081873205 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java @@ -10,10 +10,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel; import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange; -import org.jetbrains.plugins.gradle.diff.PlatformFacade; import org.jetbrains.plugins.gradle.ui.GradleDataKeys; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode; import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; @@ -33,15 +33,12 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { private Tree myTree; private GradleProjectStructureTreeModel myTreeModel; - private JPanel myContent; + private GradleProjectStructureContext myContext; - public GradleProjectStructureChangesPanel(@NotNull Project project, - @NotNull GradleProjectStructureChangesModel model, - @NotNull PlatformFacade platformFacade, - @NotNull GradleProjectStructureHelper projectStructureHelper) - { - super(project, platformFacade, projectStructureHelper, GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE); - model.addListener(new GradleProjectStructureChangeListener() { + public GradleProjectStructureChangesPanel(@NotNull Project project, @NotNull GradleProjectStructureContext context) { + super(project, GradleConstants.TOOL_WINDOW_TOOLBAR_PLACE); + myContext = context; + context.getChangesModel().addListener(new GradleProjectStructureChangeListener() { @Override public void onChanges(@NotNull final Collection oldChanges, @NotNull final Collection currentChanges) @@ -55,28 +52,30 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { }); } }); + initContent(); } - private void init() { - myContent = new JPanel(new GridBagLayout()); - myTreeModel = new GradleProjectStructureTreeModel(getProject(), getProjectFacade(), getProjectStructureHelper()); + @NotNull + public GradleProjectStructureTreeModel getTreeModel() { + return myTreeModel; + } + + @NotNull + @Override + protected JComponent buildContent() { + JPanel result = new JPanel(new GridBagLayout()); + myTreeModel = new GradleProjectStructureTreeModel(getProject(), myContext); myTree = new Tree(myTreeModel); applyInitialAppearance(myTree, (DefaultMutableTreeNode)myTreeModel.getRoot()); GridBagConstraints constraints = new GridBagConstraints(); constraints.fill = GridBagConstraints.BOTH; constraints.weightx = constraints.weighty = 1; - myContent.add(myTree, constraints); - myContent.setBackground(myTree.getBackground()); + result.add(myTree, constraints); + result.setBackground(myTree.getBackground()); CustomizationUtil.installPopupHandler(myTree, GradleConstants.ACTION_GROUP_SYNC_TREE, GradleConstants.SYNC_TREE_PLACE); - } - - @NotNull - @Override - protected JComponent buildContent() { - init(); - return myContent; + return result; } @Override diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java index 7deb8d5e3f8f..fbc42dd244f0 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java @@ -3,26 +3,24 @@ package org.jetbrains.plugins.gradle.sync; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.LibraryOrderEntry; -import com.intellij.openapi.roots.ModuleOrderEntry; -import com.intellij.openapi.roots.OrderEntry; -import com.intellij.openapi.roots.RootPolicy; +import com.intellij.openapi.roots.*; import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.config.GradleTextAttributes; import org.jetbrains.plugins.gradle.diff.*; import org.jetbrains.plugins.gradle.model.id.*; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; +import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeComparator; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor; +import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleConstants; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; import org.jetbrains.plugins.gradle.util.GradleUtil; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Model for the target project structure tree used by the gradle integration. @@ -55,18 +53,17 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { private final ObsoleteChangesDispatcher myObsoleteChangesDispatcher = new ObsoleteChangesDispatcher(); private final NewChangesDispatcher myNewChangesDispatcher = new NewChangesDispatcher(); - @NotNull private final Project myProject; - @NotNull private final PlatformFacade myPlatformFacade; - @NotNull private final GradleProjectStructureHelper myProjectStructureHelper; + @NotNull private final Project myProject; + @NotNull private final PlatformFacade myPlatformFacade; + @NotNull private final GradleProjectStructureHelper myProjectStructureHelper; + @NotNull private final Comparator> myNodeComparator; - public GradleProjectStructureTreeModel(@NotNull Project project, - @NotNull PlatformFacade platformFacade, - @NotNull GradleProjectStructureHelper projectStructureHelper) - { + public GradleProjectStructureTreeModel(@NotNull Project project, @NotNull GradleProjectStructureContext context) { super(null); myProject = project; - myPlatformFacade = platformFacade; - myProjectStructureHelper = projectStructureHelper; + myPlatformFacade = context.getPlatformFacade(); + myProjectStructureHelper = context.getProjectStructureHelper(); + myNodeComparator = new GradleProjectStructureNodeComparator(context); rebuild(); } @@ -102,6 +99,17 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { final GradleProjectStructureNode moduleNode = buildNode(moduleId, moduleId.getModuleName()); myModules.put(module.getName(), moduleNode); // Assuming that module names are unique. root.add(moduleNode); + + // Content roots + final Collection contentRoots = myPlatformFacade.getContentRoots(module); + for (ContentEntry entry : contentRoots) { + GradleContentRootId contentRootId = GradleEntityIdMapper.mapEntityToId(entry); + GradleProjectStructureNode contentRootNode + = buildNode(contentRootId, getNodeName(contentRootId, contentRoots.size() <= 1)); + moduleNode.add(contentRootNode); + } + + // Dependencies for (OrderEntry orderEntry : myPlatformFacade.getOrderEntries(module)) { orderEntry.accept(visitor, null); } @@ -112,11 +120,24 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { for (GradleProjectStructureNode dependency : dependencies) { dependenciesNode.add(dependency); } - moduleNode.add(dependenciesNode); } setRoot(root); } + + @NotNull + private static String getNodeName(@NotNull GradleContentRootId id, boolean singleRoot) { + final String name = GradleBundle.message("gradle.import.structure.tree.node.content.root"); + if (singleRoot) { + return name; + } + final String path = id.getRootPath(); + final int i = path.lastIndexOf('/'); + if (i < 0) { + return name; + } + return name + ":" + path.substring(i + 1); + } @NotNull public Project getProject() { @@ -124,7 +145,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { } private GradleProjectStructureNode buildNode(@NotNull T id, @NotNull String name) { - final GradleProjectStructureNode result = GradleUtil.buildNode(id, name); + final GradleProjectStructureNode result = new GradleProjectStructureNode(GradleUtil.buildDescriptor(id, name), myNodeComparator); result.addListener(myNodeListener); return result; } @@ -136,7 +157,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { } GradleProjectStructureNode moduleNode = getModuleNode(id); GradleProjectStructureNode result - = new GradleProjectStructureNode(GradleConstants.DEPENDENCIES_NODE_DESCRIPTOR); + = new GradleProjectStructureNode(GradleConstants.DEPENDENCIES_NODE_DESCRIPTOR, myNodeComparator); result.addListener(myNodeListener); moduleNode.add(result); myModuleDependencies.put(id.getModuleName(), result); @@ -155,6 +176,17 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { return moduleNode; } + /** + * Notifies current model that particular module roots change just has happened. + *

+ * The model is expected to update itself if necessary. + */ + public void onModuleRootsChange() { + for (GradleProjectStructureNode node : myModuleDependencies.values()) { + node.sortChildren(); + } + } + /** * Asks current model to update its state in accordance with the given changes. * @@ -379,6 +411,11 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel { public void onNodeChanged(@NotNull GradleProjectStructureNode node) { nodeChanged(node); } + + @Override + public void onNodeChildrenChanged(@NotNull GradleProjectStructureNode parent, int[] childIndices) { + nodesChanged(parent, childIndices); + } } private class NewChangesDispatcher implements GradleProjectStructureChangeVisitor { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java index c1068610d2b4..4c409cd79035 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java @@ -21,33 +21,41 @@ import java.util.concurrent.CopyOnWriteArrayList; public class GradleProjectStructureNode extends DefaultMutableTreeNode implements Iterable> { - - public static final Comparator> NODE_COMPARATOR = new Comparator>() { - @Override - public int compare(GradleProjectStructureNode n1, GradleProjectStructureNode n2) { - TextAttributesKey a1 = n1.getDescriptor().getAttributes(); - TextAttributesKey a2 = n2.getDescriptor().getAttributes(); - - // Put 'gradle-local' nodes at the top. - if (a1 == GradleTextAttributes.GRADLE_LOCAL_CHANGE && a2 != GradleTextAttributes.GRADLE_LOCAL_CHANGE) { - return -1; - } - else if (a1 != GradleTextAttributes.GRADLE_LOCAL_CHANGE && a2 == GradleTextAttributes.GRADLE_LOCAL_CHANGE) { - return 1; - } - - return n1.getDescriptor().getName().compareTo(n2.getDescriptor().getName()); - } - }; private final Set myConflictChanges = new HashSet(); private final List myListeners = new CopyOnWriteArrayList(); + + @NotNull private final Comparator> myComparator; + @NotNull private final GradleProjectStructureNodeDescriptor myDescriptor; - private final GradleProjectStructureNodeDescriptor myDescriptor; - + private boolean mySkipNotification; + + /** + * Creates new GradleProjectStructureNode object with the given descriptor and 'compare-by-name' comparator. + * + * @param descriptor target node descriptor to use within the current node + */ public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor descriptor) { + this(descriptor, new Comparator>() { + @Override + public int compare(GradleProjectStructureNode o1, GradleProjectStructureNode o2) { + return o1.getDescriptor().getName().compareTo(o2.getDescriptor().getName()); + } + }); + } + + /** + * Creates new GradleProjectStructureNode object with the given descriptor and comparator to use for organising child nodes. + * + * @param descriptor target node descriptor to use within the current node + * @param comparator comparator to use for organising child nodes of the current node + */ + public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor descriptor, + @NotNull Comparator> comparator) + { super(descriptor); myDescriptor = descriptor; + myComparator = comparator; } @NotNull @@ -69,7 +77,7 @@ public class GradleProjectStructureNode extends Defaul public void add(MutableTreeNode newChild) { for (int i = 0; i < getChildCount(); i++) { GradleProjectStructureNode node = getChildAt(i); - if (NODE_COMPARATOR.compare((GradleProjectStructureNode)newChild, node) <= 0) { + if (myComparator.compare((GradleProjectStructureNode)newChild, node) <= 0) { insert(newChild, i); // Assuming that the node listeners are notified during the nested call. return; } @@ -98,7 +106,7 @@ public class GradleProjectStructureNode extends Defaul } /** - * Asks current node to ensure that given child node is at the 'right position' (according to the {@link #NODE_COMPARATOR}. + * Asks current node to ensure that given child node is at the 'right position' (according to the {@link #myComparator}. *

* Does nothing if given node is not a child of the current node. * @@ -114,7 +122,7 @@ public class GradleProjectStructureNode extends Defaul currentPosition = i; continue; } - if (desiredPosition < 0 && NODE_COMPARATOR.compare(child, node) <= 0) { + if (desiredPosition < 0 && myComparator.compare(child, node) <= 0) { desiredPosition = i; if (currentPosition >= 0) { break; @@ -139,6 +147,34 @@ public class GradleProjectStructureNode extends Defaul return true; } + /** + * Asks current module to ensure that its children are ordered in accordance with the {@link #myComparator pre-configured comparator}. + */ + @SuppressWarnings("unchecked") + public void sortChildren() { + List> nodes = new ArrayList>(children); + Collections.sort(nodes, myComparator); + if (nodes.equals(children)) { + return; + } + + mySkipNotification = true; + try { + removeAllChildren(); + for (GradleProjectStructureNode node : nodes) { + add(node); + } + } + finally { + mySkipNotification = false; + } + int[] indices = new int[nodes.size()]; + for (int i = 0; i < indices.length; i++) { + indices[i] = i; + } + onChildrenChange(indices); + } + /** * Registers given change within the given node assuming that it is * {@link GradleTextAttributes#GRADLE_CHANGE_CONFLICT 'conflict change'}. We need to track number of such changes per-node because @@ -252,22 +288,40 @@ public class GradleProjectStructureNode extends Defaul } private void onNodeAdded(@NotNull GradleProjectStructureNode node, int index) { + if (mySkipNotification) { + return; + } for (Listener listener : myListeners) { listener.onNodeAdded(node, index); } } private void onNodeRemoved(@NotNull GradleProjectStructureNode node, int removedChildIndex) { + if (mySkipNotification) { + return; + } for (Listener listener : myListeners) { listener.onNodeRemoved(this, node, removedChildIndex); } } private void onNodeChanged(@NotNull GradleProjectStructureNode node) { + if (mySkipNotification) { + return; + } for (Listener listener : myListeners) { listener.onNodeChanged(node); } } + + private void onChildrenChange(@NotNull int[] indices) { + if (mySkipNotification) { + return; + } + for (Listener listener : myListeners) { + listener.onNodeChildrenChanged(this, indices); + } + } public interface Listener { void onNodeAdded(@NotNull GradleProjectStructureNode node, int index); @@ -275,5 +329,6 @@ public class GradleProjectStructureNode extends Defaul @NotNull GradleProjectStructureNode removedChild, int removedChildIndex); void onNodeChanged(@NotNull GradleProjectStructureNode node); + void onNodeChildrenChanged(@NotNull GradleProjectStructureNode parent, int[] childIndices); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java new file mode 100644 index 000000000000..ba275db55101 --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java @@ -0,0 +1,167 @@ +package org.jetbrains.plugins.gradle.ui; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.LibraryOrderEntry; +import com.intellij.openapi.roots.ModuleOrderEntry; +import com.intellij.openapi.roots.ModuleSourceOrderEntry; +import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.util.Ref; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.model.GradleEntityOwner; +import org.jetbrains.plugins.gradle.model.GradleEntityType; +import org.jetbrains.plugins.gradle.model.gradle.*; +import org.jetbrains.plugins.gradle.model.id.GradleEntityId; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; +import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; +import org.jetbrains.plugins.gradle.util.GradleUtil; + +import java.util.Comparator; + +/** + * Encapsulates logic of comparing 'sync project structures' tree nodes. + *

+ * Thread-safe. + * + * @author Denis Zhdanov + * @since 2/21/12 2:44 PM + */ +public class GradleProjectStructureNodeComparator implements Comparator> { + + private static final int PROJECT_WEIGHT = 0; + private static final int MODULE_WEIGHT = 1; + private static final int CONTENT_ROOT_WEIGHT = 2; + private static final int SYNTHETIC_WEIGHT = 3; + private static final int MODULE_DEPENDENCY_WEIGHT = 4; + private static final int LIBRARY_DEPENDENCY_WEIGHT = 5; + private static final int LIBRARY_WEIGHT = 6; + private static final int UNKNOWN_WEIGHT = 20; + + @NotNull private final GradleProjectStructureContext myContext; + + public GradleProjectStructureNodeComparator(@NotNull GradleProjectStructureContext context) { + myContext = context; + } + + @Override + public int compare(GradleProjectStructureNode n1, GradleProjectStructureNode n2) { + final GradleProjectStructureNodeDescriptor d1 = n1.getDescriptor(); + final GradleEntityId id1 = d1.getElement(); + + final GradleProjectStructureNodeDescriptor d2 = n2.getDescriptor(); + final GradleEntityId id2 = d2.getElement(); + + // Put 'gradle-local' nodes at the top. + if (id1.getOwner() == GradleEntityOwner.GRADLE && id2.getOwner() == GradleEntityOwner.INTELLIJ) { + return -1; + } + else if (id1.getOwner() == GradleEntityOwner.INTELLIJ && id2.getOwner() == GradleEntityOwner.GRADLE) { + return 1; + } + + // Compare by weight. + int weight1 = getWeight(id1); + int weight2 = getWeight(id2); + if (weight1 != weight2) { + return weight1 - weight2; + } + + // Compare by name. + return d1.getName().compareTo(d2.getName()); + } + + private int getWeight(@NotNull GradleEntityId id) { + if (id.getType() == GradleEntityType.SYNTHETIC) { + return SYNTHETIC_WEIGHT; + } + final Object entity = id.mapToEntity(myContext); + final Ref result = new Ref(); + if (entity instanceof GradleEntity) { + ((GradleEntity)entity).invite(new GradleEntityVisitor() { + @Override + public void visit(@NotNull GradleProject project) { + result.set(PROJECT_WEIGHT); + } + + @Override + public void visit(@NotNull GradleModule module) { + result.set(MODULE_WEIGHT); + } + + @Override + public void visit(@NotNull GradleContentRoot contentRoot) { + result.set(CONTENT_ROOT_WEIGHT); + } + + @Override + public void visit(@NotNull GradleLibrary library) { + result.set(LIBRARY_WEIGHT); + } + + @Override + public void visit(@NotNull GradleModuleDependency dependency) { + result.set(MODULE_DEPENDENCY_WEIGHT); + } + + @Override + public void visit(@NotNull GradleLibraryDependency dependency) { + result.set(LIBRARY_DEPENDENCY_WEIGHT); + } + }); + } + else { + GradleUtil.dispatch(entity, new IntellijEntityVisitor() { + @Override + public void visit(@NotNull Project project) { + result.set(PROJECT_WEIGHT); + } + + @Override + public void visit(@NotNull Module module) { + result.set(MODULE_WEIGHT); + } + + @Override + public void visit(@NotNull ModuleAwareContentRoot contentRoot) { + int i = 0; + for (OrderEntry entry : myContext.getPlatformFacade().getOrderEntries(contentRoot.getModule())) { + if (entry instanceof ModuleSourceOrderEntry) { + result.set(i); + return; + } + i++; + } + result.set(UNKNOWN_WEIGHT); + } + + @Override + public void visit(@NotNull LibraryOrderEntry libraryDependency) { + result.set(getWeight(libraryDependency.getOwnerModule(), libraryDependency)); + } + + @Override + public void visit(@NotNull ModuleOrderEntry moduleDependency) { + result.set(getWeight(moduleDependency.getOwnerModule(), moduleDependency)); + } + }); + } + try { + return result.get(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + } + + private int getWeight(@NotNull Module module, @NotNull Object entry) { + int i = 0; + for (OrderEntry orderEntry : myContext.getPlatformFacade().getOrderEntries(module)) { + if (orderEntry.equals(entry)) { + return i; + } + i++; + } + return UNKNOWN_WEIGHT; + } +} diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java index 7fe40ad3f877..d364f6d13cdf 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleToolWindowFactory.java @@ -1,25 +1,34 @@ package org.jetbrains.plugins.gradle.ui; -import com.intellij.openapi.components.ServiceManager; +import com.intellij.ProjectTopics; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootEvent; +import com.intellij.openapi.roots.ModuleRootListener; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.impl.ContentImpl; -import org.jetbrains.plugins.gradle.diff.PlatformFacade; -import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesPanel; -import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext; public class GradleToolWindowFactory implements ToolWindowFactory { @Override public void createToolWindowContent(final Project project, final ToolWindow toolWindow) { - final GradleProjectStructureChangesModel model = project.getComponent(GradleProjectStructureChangesModel.class); - final PlatformFacade facade = ServiceManager.getService(PlatformFacade.class); - final GradleProjectStructureHelper helper = project.getComponent(GradleProjectStructureHelper.class); + final GradleProjectStructureContext context = project.getComponent(GradleProjectStructureContext.class); - final GradleProjectStructureChangesPanel panel = new GradleProjectStructureChangesPanel(project, model, facade, helper); + final GradleProjectStructureChangesPanel panel = new GradleProjectStructureChangesPanel(project, context); final String syncTitle = GradleBundle.message("gradle.sync.title.tab"); toolWindow.getContentManager().addContent(new ContentImpl(panel, syncTitle, true)); + project.getMessageBus().connect(project).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { + @Override + public void beforeRootsChange(ModuleRootEvent event) { + } + + @Override + public void rootsChanged(ModuleRootEvent event) { + // The general idea is to change dependencies order at the UI if they are changed at the module settings. + panel.getTreeModel().onModuleRootsChange(); + } + }); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityMappingContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleProjectStructureContext.java similarity index 51% rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityMappingContext.java rename to plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleProjectStructureContext.java index 64f1560efd2c..39aaed5e7c19 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/id/GradleEntityMappingContext.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleProjectStructureContext.java @@ -1,25 +1,30 @@ -package org.jetbrains.plugins.gradle.model.id; +package org.jetbrains.plugins.gradle.util; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.diff.PlatformFacade; import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; /** - * Facades all services necessary for the {@link GradleEntityId#mapToEntity(GradleEntityMappingContext) 'entity id -> entity} - * mapping. + * Facades all services necessary for the 'sync project changes' processing. *

* Thread-safe. * * @author Denis Zhdanov * @since 2/14/12 1:26 PM */ -public class GradleEntityMappingContext { +public class GradleProjectStructureContext { @NotNull private final GradleProjectStructureHelper myProjectStructureHelper; + @NotNull private final PlatformFacade myPlatformFacade; @NotNull private final GradleProjectStructureChangesModel myChangesModel; - public GradleEntityMappingContext(GradleProjectStructureHelper projectStructureHelper, GradleProjectStructureChangesModel changesModel) { + public GradleProjectStructureContext(@NotNull GradleProjectStructureHelper projectStructureHelper, + @NotNull PlatformFacade platformFacade, + @NotNull GradleProjectStructureChangesModel changesModel) + { myProjectStructureHelper = projectStructureHelper; + myPlatformFacade = platformFacade; myChangesModel = changesModel; } @@ -28,6 +33,11 @@ public class GradleEntityMappingContext { return myProjectStructureHelper; } + @NotNull + public PlatformFacade getPlatformFacade() { + return myPlatformFacade; + } + @NotNull public GradleProjectStructureChangesModel getChangesModel() { return myChangesModel; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java index 3977afeb7df3..51fa6ffc6ee5 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleUtil.java @@ -27,10 +27,10 @@ import org.jetbrains.plugins.gradle.config.GradleSettings; import org.jetbrains.plugins.gradle.model.gradle.GradleProject; import org.jetbrains.plugins.gradle.model.id.GradleEntityId; import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; import org.jetbrains.plugins.gradle.remote.GradleApiException; import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask; import org.jetbrains.plugins.gradle.ui.GradleIcons; -import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor; import javax.swing.*; @@ -201,7 +201,7 @@ public class GradleUtil { }); return gradleProject.get(); } - + /** * Tries to dispatch given entity via the given visitor. * @@ -215,6 +215,9 @@ public class GradleUtil { else if (entity instanceof Module) { visitor.visit(((Module)entity)); } + else if (entity instanceof ModuleAwareContentRoot) { + visitor.visit(((ModuleAwareContentRoot)entity)); + } else if (entity instanceof LibraryOrderEntry) { visitor.visit(((LibraryOrderEntry)entity)); } @@ -227,16 +230,6 @@ public class GradleUtil { return new GradleProjectStructureNodeDescriptor(id, name, id.getType().getIcon()); } - @NotNull - public static GradleProjectStructureNode buildNode(@NotNull T id) { - return new GradleProjectStructureNode(buildDescriptor(id, id.toString())); - } - - @NotNull - public static GradleProjectStructureNode buildNode(@NotNull T id, @NotNull String name) { - return new GradleProjectStructureNode(buildDescriptor(id, name)); - } - private interface TaskUnderProgress { void execute(@NotNull ProgressIndicator indicator); } diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy index d97f7288a24e..7d2bba43708c 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractGradleTest.groovy @@ -13,6 +13,7 @@ import org.picocontainer.defaults.DefaultPicoContainer import org.jetbrains.plugins.gradle.diff.* import static org.junit.Assert.fail +import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext /** * @author Denis Zhdanov @@ -47,6 +48,7 @@ public abstract class AbstractGradleTest { container.registerComponentImplementation(GradleLibraryDependencyStructureChangesCalculator) container.registerComponentImplementation(GradleLibraryStructureChangesCalculator) container.registerComponentImplementation(GradleEntityIdMapper) + container.registerComponentImplementation(GradleProjectStructureContext) configureContainer(container) changesModel = container.getComponentInstance(GradleProjectStructureChangesModel) as GradleProjectStructureChangesModel diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractProjectBuilder.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractProjectBuilder.groovy index 4b6ad6712fb7..d3a4b3c72771 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractProjectBuilder.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/AbstractProjectBuilder.groovy @@ -16,15 +16,18 @@ public abstract class AbstractProjectBuilder extends BuilderSupport { /** [module name; module] */ def modules = [:] + + /** [module; content roots] */ + def contentRoots = [:].withDefault { [] } /** Holds (library name; library) pairs for the active configuration. */ def libraries = [:] /** [module; dependency list] */ - def libraryDependencies = [:].withDefault {[]} + def libraryDependencies = [:].withDefault { [] } /** [module; dependency list] */ - def moduleDependencies = [:].withDefault {[]} + def moduleDependencies = [:].withDefault { [] } /** * Holds (library name; library) pairs for the whole test. I.e. there is a possible case that we define particular configuration diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/IntellijProjectBuilder.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/IntellijProjectBuilder.groovy index 9a694bef6d3e..85f0c6ce2507 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/IntellijProjectBuilder.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/testutil/IntellijProjectBuilder.groovy @@ -35,7 +35,8 @@ class IntellijProjectBuilder extends AbstractProjectBuilder { getOrderEntries: { libraryDependencies[it] + moduleDependencies[it] }, getProjectIcon: { IconLoader.getIcon("/nodes/ideaProject.png") }, getLocalFileSystemPath: { it.path }, - getProjectLibraryTable: { projectLibraryTable } + getProjectLibraryTable: { projectLibraryTable }, + getContentRoots: { contentRoots[it] } ] /** (library name - (library root type - paths)). */ def libraryPaths = [:].withDefault { [:] }