mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes
1. Started work for supporting content roots at the 'sync project structures'; 2. Module dependencies order is kept in sync with the module settings now;
This commit is contained in:
@@ -80,6 +80,9 @@
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.gradle.util.GradleProjectStructureContext</implementation-class>
|
||||
</component>
|
||||
<component>
|
||||
<implementation-class>org.jetbrains.plugins.gradle.importing.GradleLocalNodeImportHelper</implementation-class>
|
||||
</component>
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<Module> getModules(@NotNull Project project);
|
||||
|
||||
|
||||
@NotNull
|
||||
Collection<ModuleAwareContentRoot> getContentRoots(@NotNull Module module);
|
||||
|
||||
@NotNull
|
||||
Collection<OrderEntry> getOrderEntries(@NotNull Module module);
|
||||
|
||||
|
||||
@@ -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<ModuleAwareContentRoot> getContentRoots(@NotNull final Module module) {
|
||||
final ContentEntry[] entries = ModuleRootManager.getInstance(module).getContentEntries();
|
||||
if (entries == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return ContainerUtil.map(entries, new Function<ContentEntry, ModuleAwareContentRoot>() {
|
||||
@Override
|
||||
public ModuleAwareContentRoot fun(ContentEntry entry) {
|
||||
return new ModuleAwareContentRoot(module, entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<OrderEntry> getOrderEntries(@NotNull Module module) {
|
||||
|
||||
@@ -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 + "'";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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).
|
||||
* <p/>
|
||||
* We need an entity id, for example, at the <code>'sync project structure'</code> 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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
+2
-1
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
+2
-1
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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);
|
||||
|
||||
-26
@@ -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) {
|
||||
}
|
||||
}
|
||||
+111
@@ -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();
|
||||
}
|
||||
}
|
||||
+20
-21
@@ -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<GradleProjectStructureChange> oldChanges,
|
||||
@NotNull final Collection<GradleProjectStructureChange> 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
|
||||
|
||||
+57
-20
@@ -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<GradleProjectStructureNode<?>> 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<GradleModuleId> moduleNode = buildNode(moduleId, moduleId.getModuleName());
|
||||
myModules.put(module.getName(), moduleNode); // Assuming that module names are unique.
|
||||
root.add(moduleNode);
|
||||
|
||||
// Content roots
|
||||
final Collection<ModuleAwareContentRoot> contentRoots = myPlatformFacade.getContentRoots(module);
|
||||
for (ContentEntry entry : contentRoots) {
|
||||
GradleContentRootId contentRootId = GradleEntityIdMapper.mapEntityToId(entry);
|
||||
GradleProjectStructureNode<GradleContentRootId> 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 <T extends GradleEntityId> GradleProjectStructureNode<T> buildNode(@NotNull T id, @NotNull String name) {
|
||||
final GradleProjectStructureNode<T> result = GradleUtil.buildNode(id, name);
|
||||
final GradleProjectStructureNode<T> result = new GradleProjectStructureNode<T>(GradleUtil.buildDescriptor(id, name), myNodeComparator);
|
||||
result.addListener(myNodeListener);
|
||||
return result;
|
||||
}
|
||||
@@ -136,7 +157,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
|
||||
}
|
||||
GradleProjectStructureNode<GradleModuleId> moduleNode = getModuleNode(id);
|
||||
GradleProjectStructureNode<GradleSyntheticId> result
|
||||
= new GradleProjectStructureNode<GradleSyntheticId>(GradleConstants.DEPENDENCIES_NODE_DESCRIPTOR);
|
||||
= new GradleProjectStructureNode<GradleSyntheticId>(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.
|
||||
* <p/>
|
||||
* The model is expected to update itself if necessary.
|
||||
*/
|
||||
public void onModuleRootsChange() {
|
||||
for (GradleProjectStructureNode<GradleSyntheticId> 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 {
|
||||
|
||||
+78
-23
@@ -21,33 +21,41 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
public class GradleProjectStructureNode<T extends GradleEntityId> extends DefaultMutableTreeNode
|
||||
implements Iterable<GradleProjectStructureNode<?>>
|
||||
{
|
||||
|
||||
public static final Comparator<GradleProjectStructureNode<?>> NODE_COMPARATOR = new Comparator<GradleProjectStructureNode<?>>() {
|
||||
@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<GradleProjectStructureChange> myConflictChanges = new HashSet<GradleProjectStructureChange>();
|
||||
private final List<Listener> myListeners = new CopyOnWriteArrayList<Listener>();
|
||||
|
||||
@NotNull private final Comparator<GradleProjectStructureNode<?>> myComparator;
|
||||
@NotNull private final GradleProjectStructureNodeDescriptor<T> myDescriptor;
|
||||
|
||||
private final GradleProjectStructureNodeDescriptor<T> myDescriptor;
|
||||
|
||||
private boolean mySkipNotification;
|
||||
|
||||
/**
|
||||
* Creates new <code>GradleProjectStructureNode</code> 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<T> descriptor) {
|
||||
this(descriptor, new Comparator<GradleProjectStructureNode<?>>() {
|
||||
@Override
|
||||
public int compare(GradleProjectStructureNode<?> o1, GradleProjectStructureNode<?> o2) {
|
||||
return o1.getDescriptor().getName().compareTo(o2.getDescriptor().getName());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new <code>GradleProjectStructureNode</code> 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<T> descriptor,
|
||||
@NotNull Comparator<GradleProjectStructureNode<?>> comparator)
|
||||
{
|
||||
super(descriptor);
|
||||
myDescriptor = descriptor;
|
||||
myComparator = comparator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -69,7 +77,7 @@ public class GradleProjectStructureNode<T extends GradleEntityId> 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<T extends GradleEntityId> 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}.
|
||||
* <p/>
|
||||
* Does nothing if given node is not a child of the current node.
|
||||
*
|
||||
@@ -114,7 +122,7 @@ public class GradleProjectStructureNode<T extends GradleEntityId> 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<T extends GradleEntityId> 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<GradleProjectStructureNode<?>> nodes = new ArrayList<GradleProjectStructureNode<?>>(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<T extends GradleEntityId> 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<T extends GradleEntityId> extends Defaul
|
||||
@NotNull GradleProjectStructureNode<?> removedChild,
|
||||
int removedChildIndex);
|
||||
void onNodeChanged(@NotNull GradleProjectStructureNode<?> node);
|
||||
void onNodeChildrenChanged(@NotNull GradleProjectStructureNode<?> parent, int[] childIndices);
|
||||
}
|
||||
}
|
||||
|
||||
+167
@@ -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.
|
||||
* <p/>
|
||||
* Thread-safe.
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 2/21/12 2:44 PM
|
||||
*/
|
||||
public class GradleProjectStructureNodeComparator implements Comparator<GradleProjectStructureNode<?>> {
|
||||
|
||||
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<? extends GradleEntityId> d1 = n1.getDescriptor();
|
||||
final GradleEntityId id1 = d1.getElement();
|
||||
|
||||
final GradleProjectStructureNodeDescriptor<? extends GradleEntityId> 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<Integer> result = new Ref<Integer>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+15
-5
@@ -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.
|
||||
* <p/>
|
||||
* 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;
|
||||
@@ -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<T>(id, name, id.getType().getIcon());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends GradleEntityId> GradleProjectStructureNode<T> buildNode(@NotNull T id) {
|
||||
return new GradleProjectStructureNode<T>(buildDescriptor(id, id.toString()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T extends GradleEntityId> GradleProjectStructureNode<T> buildNode(@NotNull T id, @NotNull String name) {
|
||||
return new GradleProjectStructureNode<T>(buildDescriptor(id, name));
|
||||
}
|
||||
|
||||
private interface TaskUnderProgress {
|
||||
void execute(@NotNull ProgressIndicator indicator);
|
||||
}
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+5
-2
@@ -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
|
||||
|
||||
+2
-1
@@ -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 { [:] }
|
||||
|
||||
Reference in New Issue
Block a user