diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectCoordinate.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectCoordinate.java new file mode 100644 index 000000000000..2448e3600dda --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectCoordinate.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.externalSystem.model.project; + +/** + * @author Vladislav.Soroka + * @since 4/14/2015 + */ +public interface ProjectCoordinate { + String getGroupId(); + + String getArtifactId(); + + String getVersion(); +} diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectData.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectData.java index 10d332bddc0d..43a723bb966a 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectData.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectData.java @@ -17,6 +17,8 @@ public class ProjectData extends AbstractNamedData implements ExternalConfigPath @NotNull private final String myLinkedExternalProjectPath; @NotNull private String myIdeProjectFileDirectoryPath; + private String myGroup; + private String myVersion; @Deprecated public ProjectData(@NotNull ProjectSystemId owner, @@ -87,4 +89,20 @@ public class ProjectData extends AbstractNamedData implements ExternalConfigPath public String getId() { return ""; } + + public String getGroup() { + return myGroup; + } + + public void setGroup(String group) { + myGroup = group; + } + + public String getVersion() { + return myVersion; + } + + public void setVersion(String version) { + myVersion = version; + } } diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectId.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectId.java new file mode 100644 index 000000000000..8540d1ea0724 --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ProjectId.java @@ -0,0 +1,106 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.externalSystem.model.project; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.Serializable; + +public class ProjectId implements Serializable, ProjectCoordinate { + public static final String UNKNOWN_VALUE = "Unknown"; + + @Nullable private final String myGroupId; + @Nullable private final String myArtifactId; + @Nullable private final String myVersion; + + public ProjectId(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) { + myGroupId = groupId; + myArtifactId = artifactId; + myVersion = version; + } + + @Nullable + public String getGroupId() { + return myGroupId; + } + + @Nullable + public String getArtifactId() { + return myArtifactId; + } + + @Nullable + public String getVersion() { + return myVersion; + } + + @NotNull + public String getKey() { + StringBuilder builder = new StringBuilder(); + + append(builder, myGroupId); + append(builder, myArtifactId); + append(builder, myVersion); + + return builder.toString(); + } + + @NotNull + public String getDisplayString() { + return getKey(); + } + + public static void append(StringBuilder builder, String part) { + if (builder.length() != 0) builder.append(':'); + builder.append(part == null ? "" : part); + } + + @Override + public String toString() { + return getDisplayString(); + } + + public boolean equals(@Nullable String groupId, @Nullable String artifactId) { + if (myArtifactId != null ? !myArtifactId.equals(artifactId) : artifactId != null) return false; + if (myGroupId != null ? !myGroupId.equals(groupId) : groupId != null) return false; + return true; + } + + public boolean equals(@Nullable String groupId, @Nullable String artifactId, @Nullable String version) { + if (!equals(groupId, artifactId)) return false; + if (myVersion != null ? !myVersion.equals(version) : version != null) return false; + return true; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ProjectId other = (ProjectId)o; + return equals(other.getGroupId(), other.myArtifactId, other.myVersion); + } + + @Override + public int hashCode() { + int result; + result = (myGroupId != null ? myGroupId.hashCode() : 0); + result = 31 * result + (myArtifactId != null ? myArtifactId.hashCode() : 0); + result = 31 * result + (myVersion != null ? myVersion.hashCode() : 0); + return result; + } +} diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/PlatformFacade.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/PlatformFacade.java index 75c1405c8ded..8407c432904e 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/PlatformFacade.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/service/project/PlatformFacade.java @@ -1,11 +1,20 @@ package com.intellij.openapi.externalSystem.service.project; +import com.intellij.openapi.externalSystem.model.project.LibraryData; +import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData; +import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleOrderEntry; import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -47,4 +56,35 @@ public interface PlatformFacade { */ @NotNull String getLocalFileSystemPath(@NotNull VirtualFile file); + + /** + * Creates a module of the specified type at the specified path and adds it to the project + * to which the module manager is related. {@link #commit()} must be called to + * bring the changes in effect. + * + * + * @param project + * @param filePath the path at which the module is created. + * @param moduleTypeId the ID of the module type to create. + * @return the module instance. + */ + Module newModule(Project project, @NotNull @NonNls String filePath, final String moduleTypeId); + + ModifiableRootModel getModuleModifiableModel(Module module); + + @Nullable + Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject); + + @Nullable + Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject); + + @Nullable + Library findIdeLibrary(@NotNull LibraryData libraryData, @NotNull Project ideProject); + + @SuppressWarnings("MethodMayBeStatic") + @Nullable + ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model); + + @Nullable + OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemViewGearAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemViewGearAction.java index a56c299f82d7..b9e7b2dbcd60 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemViewGearAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemViewGearAction.java @@ -16,7 +16,7 @@ package com.intellij.openapi.externalSystem.action; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; */ public abstract class ExternalSystemViewGearAction extends ExternalSystemToggleAction { - private ExternalProjectsView myView; + private ExternalProjectsViewImpl myView; @Override protected boolean isEnabled(AnActionEvent e) { @@ -36,28 +36,28 @@ public abstract class ExternalSystemViewGearAction extends ExternalSystemToggleA @Override protected boolean doIsSelected(AnActionEvent e) { - final ExternalProjectsView view = getView(); + final ExternalProjectsViewImpl view = getView(); return view != null && isSelected(view); } @Override public void setSelected(AnActionEvent e, boolean state) { - final ExternalProjectsView view = getView(); + final ExternalProjectsViewImpl view = getView(); if (view != null){ setSelected(view, state); } } - protected abstract boolean isSelected(@NotNull ExternalProjectsView view); + protected abstract boolean isSelected(@NotNull ExternalProjectsViewImpl view); - protected abstract void setSelected(@NotNull ExternalProjectsView view, boolean value); + protected abstract void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value); @Nullable - protected ExternalProjectsView getView() { + protected ExternalProjectsViewImpl getView() { return myView; } - public void setView(ExternalProjectsView view) { + public void setView(ExternalProjectsViewImpl view) { myView = view; } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/RefreshExternalProjectAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/RefreshExternalProjectAction.java index b95465377d5a..fe3e6c8c2609 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/RefreshExternalProjectAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/RefreshExternalProjectAction.java @@ -1,8 +1,6 @@ package com.intellij.openapi.externalSystem.action; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData; @@ -10,23 +8,15 @@ import com.intellij.openapi.externalSystem.model.project.ExternalConfigPathAware import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; -import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; -import com.intellij.openapi.externalSystem.view.ProjectNode; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.Collections; import java.util.List; /** @@ -70,31 +60,7 @@ public class RefreshExternalProjectAction extends ExternalSystemNodeAction externalProject) { - if (externalProject == null) { - return; - } - ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) { - @Override - public void execute() { - ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() { - @Override - public void run() { - projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), project, true); - } - }); - } - }); - } - - @Override - public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) { - } - }, false, ProgressExecutionMode.IN_BACKGROUND_ASYNC); + project, projectSystemId, externalConfigPathAware.getLinkedExternalProjectPath(), false, ProgressExecutionMode.IN_BACKGROUND_ASYNC); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/GroupTasksAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/GroupTasksAction.java index a538267d4632..cc86dca6614b 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/GroupTasksAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/GroupTasksAction.java @@ -16,7 +16,7 @@ package com.intellij.openapi.externalSystem.action.task; import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction; -import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import org.jetbrains.annotations.NotNull; /** @@ -25,12 +25,12 @@ import org.jetbrains.annotations.NotNull; */ public class GroupTasksAction extends ExternalSystemViewGearAction { @Override - protected boolean isSelected(@NotNull ExternalProjectsView view) { + protected boolean isSelected(@NotNull ExternalProjectsViewImpl view) { return view.getGroupTasks(); } @Override - protected void setSelected(@NotNull ExternalProjectsView view, boolean value) { + protected void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value) { view.setGroupTasks(value); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ShowInheritedTasksAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ShowInheritedTasksAction.java index 53d333191c83..b66424b8fa71 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ShowInheritedTasksAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/task/ShowInheritedTasksAction.java @@ -16,7 +16,7 @@ package com.intellij.openapi.externalSystem.action.task; import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction; -import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import org.jetbrains.annotations.NotNull; /** @@ -25,12 +25,12 @@ import org.jetbrains.annotations.NotNull; */ public class ShowInheritedTasksAction extends ExternalSystemViewGearAction { @Override - protected boolean isSelected(@NotNull ExternalProjectsView view) { + protected boolean isSelected(@NotNull ExternalProjectsViewImpl view) { return view.showInheritedTasks(); } @Override - protected void setSelected(@NotNull ExternalProjectsView view, boolean value) { + protected void setSelected(@NotNull ExternalProjectsViewImpl view, boolean value) { view.setShowInheritedTasks(value); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java index 680c4e617a32..9290cf60b9af 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/notification/ExternalSystemNotificationManager.java @@ -17,6 +17,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -153,7 +154,8 @@ public class ExternalSystemNotificationManager { NotificationGroup group; if (notificationData.getBalloonGroup() == null) { ExternalProjectsView externalProjectsView = ExternalProjectsManager.getInstance(myProject).getExternalProjectsView(externalSystemId); - group = externalProjectsView != null ? externalProjectsView.getNotificationGroup() : null; + group = externalProjectsView instanceof ExternalProjectsViewImpl ? + ((ExternalProjectsViewImpl)externalProjectsView).getNotificationGroup() : null; } else { final NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationData.getBalloonGroup()); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/PlatformFacadeImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/PlatformFacadeImpl.java index d3875f949237..b2f0b9ac7e2e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/PlatformFacadeImpl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/PlatformFacadeImpl.java @@ -1,17 +1,21 @@ package com.intellij.openapi.externalSystem.service.project; +import com.intellij.openapi.externalSystem.model.project.*; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; +import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.Collection; /** * @author Denis Zhdanov @@ -42,4 +46,95 @@ public class PlatformFacadeImpl implements PlatformFacade { public String getLocalFileSystemPath(@NotNull VirtualFile file) { return ExternalSystemApiUtil.getLocalFileSystemPath(file); } + + @Override + public Module newModule(Project project, @NotNull @NonNls String filePath, String moduleTypeId) { + final ModuleManager moduleManager = ModuleManager.getInstance(project); + return moduleManager.newModule(filePath, moduleTypeId); + } + + @Override + public ModifiableRootModel getModuleModifiableModel(Module module) { + final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + return moduleRootManager.getModifiableModel(); + } + + @Nullable + @Override + public Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject) { + return findIdeModule(module.getInternalName(), ideProject); + } + + @Nullable + @Override + public Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject) { + for (Module module : getModules(ideProject)) { + if (ideModuleName.equals(module.getName())) { + return module; + } + } + return null; + } + + @Nullable + @Override + public Library findIdeLibrary(@NotNull final LibraryData libraryData, @NotNull Project ideProject) { + final LibraryTable libraryTable = getProjectLibraryTable(ideProject); + for (Library ideLibrary : libraryTable.getLibraries()) { + if (ExternalSystemApiUtil.isRelated(ideLibrary, libraryData)) return ideLibrary; + } + return null; + } + + public boolean isOrphanProjectLibrary(@NotNull final Library library, + @NotNull final Iterable ideModules) { + RootPolicy visitor = new RootPolicy() { + @Override + public Boolean visitLibraryOrderEntry(LibraryOrderEntry ideDependency, Boolean value) { + return !ideDependency.isModuleLevel() && library == ideDependency.getLibrary(); + } + }; + for (Module module : ideModules) { + for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) { + if (entry.accept(visitor, false)) return false; + } + } + return true; + } + + @SuppressWarnings("MethodMayBeStatic") + @Nullable + @Override + public ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model) { + for (OrderEntry entry : model.getOrderEntries()) { + if (entry instanceof ModuleOrderEntry) { + ModuleOrderEntry candidate = (ModuleOrderEntry)entry; + if (dependency.getInternalName().equals(candidate.getModuleName()) && + dependency.getScope().equals(candidate.getScope())) { + return candidate; + } + } + } + return null; + } + + @Nullable + @Override + public OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project) { + Module ownerIdeModule = findIdeModule(data.getOwnerModule(), project); + if (ownerIdeModule == null) return null; + + ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(ownerIdeModule); + + for (OrderEntry entry : moduleRootManager.getOrderEntries()) { + if (entry instanceof LibraryOrderEntry) { + if (((LibraryOrderEntry)entry).isModuleLevel() && data.getLevel() != LibraryLevel.MODULE) continue; + } + + if (data.getInternalName().equals(entry.getPresentableName())) { + return entry; + } + } + return null; + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureHelper.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureHelper.java index 81769681771d..3ba4ffbd5bb4 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureHelper.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/ProjectStructureHelper.java @@ -1,12 +1,13 @@ package com.intellij.openapi.externalSystem.service.project; -import com.intellij.openapi.externalSystem.model.project.*; -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.model.project.LibraryData; +import com.intellij.openapi.externalSystem.model.project.LibraryDependencyData; +import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.libraries.LibraryTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,26 +27,17 @@ public class ProjectStructureHelper { @Nullable public Module findIdeModule(@NotNull ModuleData module, @NotNull Project ideProject) { - return findIdeModule(module.getInternalName(), ideProject); + return myFacade.findIdeModule(module, ideProject); } @Nullable public Module findIdeModule(@NotNull String ideModuleName, @NotNull Project ideProject) { - for (Module module : myFacade.getModules(ideProject)) { - if (ideModuleName.equals(module.getName())) { - return module; - } - } - return null; + return myFacade.findIdeModule(ideModuleName, ideProject); } @Nullable public Library findIdeLibrary(@NotNull final LibraryData libraryData, @NotNull Project ideProject) { - final LibraryTable libraryTable = myFacade.getProjectLibraryTable(ideProject); - for (Library ideLibrary : libraryTable.getLibraries()) { - if (ExternalSystemApiUtil.isRelated(ideLibrary, libraryData)) return ideLibrary; - } - return null; + return myFacade.findIdeLibrary(libraryData, ideProject); } public static boolean isOrphanProjectLibrary(@NotNull final Library library, @@ -67,34 +59,11 @@ public class ProjectStructureHelper { @SuppressWarnings("MethodMayBeStatic") @Nullable public ModuleOrderEntry findIdeModuleDependency(@NotNull ModuleDependencyData dependency, @NotNull ModifiableRootModel model) { - for (OrderEntry entry : model.getOrderEntries()) { - if (entry instanceof ModuleOrderEntry) { - ModuleOrderEntry candidate = (ModuleOrderEntry)entry; - if (dependency.getInternalName().equals(candidate.getModuleName()) && - dependency.getScope().equals(candidate.getScope())) { - return candidate; - } - } - } - return null; + return myFacade.findIdeModuleDependency(dependency, model); } @Nullable public OrderEntry findIdeModuleOrderEntry(LibraryDependencyData data, Project project) { - Module ownerIdeModule = findIdeModule(data.getOwnerModule(), project); - if (ownerIdeModule == null) return null; - - ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(ownerIdeModule); - - for (OrderEntry entry : moduleRootManager.getOrderEntries()) { - if (entry instanceof LibraryOrderEntry) { - if (((LibraryOrderEntry)entry).isModuleLevel() && data.getLevel() != LibraryLevel.MODULE) continue; - } - - if (data.getInternalName().equals(entry.getPresentableName())) { - return entry; - } - } - return null; + return myFacade.findIdeModuleOrderEntry(data, project); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java index db5766730eac..3cf66f3e7a4f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractDependencyDataService.java @@ -15,7 +15,10 @@ */ package com.intellij.openapi.externalSystem.service.project.manage; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.project.AbstractDependencyData; +import com.intellij.openapi.externalSystem.service.project.PlatformFacade; import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; @@ -36,9 +39,16 @@ import java.util.Map; */ @Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER) public abstract class AbstractDependencyDataService, I extends ExportableOrderEntry> - implements ProjectDataService + implements ProjectDataServiceEx { + public void importData(@NotNull final Collection> toImport, + @NotNull final Project project, + final boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + importData(toImport, project, platformFacade, synchronous); + } + public void setScope(@NotNull final DependencyScope scope, @NotNull final ExportableOrderEntry dependency, boolean synchronous) { ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(dependency.getOwnerModule()) { @Override @@ -69,8 +79,8 @@ public abstract class AbstractDependencyDataService consumer) { // We need to get an up-to-date modifiable model to work with. - ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(entry.getOwnerModule()); - final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel(); + final ModifiableRootModel moduleRootModel = + ModifiableModelsProvider.SERVICE.getInstance().getModuleModifiableModel(entry.getOwnerModule()); try { // The thing is that intellij created order entry objects every time new modifiable model is created, // that's why we can't use target dependency object as is but need to get a reference to the current @@ -89,13 +99,22 @@ public abstract class AbstractDependencyDataService toRemove, @NotNull Project project, boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + removeData(toRemove, project, platformFacade, synchronous); + } + + @Override + public void removeData(@NotNull Collection toRemove, + @NotNull Project project, + @NotNull final PlatformFacade platformFacade, + boolean synchronous) { if (toRemove.isEmpty()) { return; } Map> byModule = groupByModule(toRemove); for (Map.Entry> entry : byModule.entrySet()) { - removeData(entry.getValue(), entry.getKey(), synchronous); + removeData(entry.getValue(), entry.getKey(), platformFacade, synchronous); } } @@ -111,8 +130,11 @@ public abstract class AbstractDependencyDataService toRemove, @NotNull final Module module, boolean synchronous) { + + protected void removeData(@NotNull Collection toRemove, + @NotNull final Module module, + @NotNull final PlatformFacade platformFacade, + boolean synchronous) { if (toRemove.isEmpty()) { return; } @@ -120,8 +142,7 @@ public abstract class AbstractDependencyDataService { +public class ContentRootDataService implements ProjectDataServiceEx { private static final Logger LOG = Logger.getInstance("#" + ContentRootDataService.class.getName()); - @NotNull private final ProjectStructureHelper myProjectStructureHelper; - - public ContentRootDataService(@NotNull ProjectStructureHelper helper) { - myProjectStructureHelper = helper; - } - @NotNull @Override public Key getTargetDataKey() { return ProjectKeys.CONTENT_ROOT; } + public void importData(@NotNull final Collection> toImport, + @NotNull final Project project, + final boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + importData(toImport, project, platformFacade, synchronous); + } + @Override public void importData(@NotNull final Collection> toImport, @NotNull final Project project, - boolean synchronous) { + @NotNull final PlatformFacade platformFacade, + final boolean synchronous) { if (toImport.isEmpty()) { return; } Map, List>> byModule = ExternalSystemApiUtil.groupBy(toImport, ProjectKeys.MODULE); for (Map.Entry, List>> entry : byModule.entrySet()) { - final Module module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project); + final Module module = platformFacade.findIdeModule(entry.getKey().getData(), project); if (module == null) { LOG.warn(String.format( "Can't import content roots. Reason: target module (%s) is not found at the ide. Content roots: %s", @@ -237,6 +240,13 @@ public class ContentRootDataService implements ProjectDataService toRemove, @NotNull Project project, boolean synchronous) { } + @Override + public void removeData(@NotNull Collection toRemove, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { + } + private static String toVfsUrl(@NotNull String path) { return LocalFileSystem.PROTOCOL_PREFIX + path; } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java index 0c61d23d6a7a..a8f634b12848 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java @@ -31,6 +31,7 @@ import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings; +import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.module.ModuleTypeId; import com.intellij.openapi.project.Project; @@ -47,6 +48,7 @@ import java.io.*; import java.util.Collection; import java.util.Iterator; import java.util.Map; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -189,6 +191,22 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent { changed.set(true); } + + // restore linked project sub-modules + ExternalProjectSettings linkedProjectSettings = + manager.getSettingsProvider().fun(myProject).getLinkedProjectSettings(externalProjectPath); + if (linkedProjectSettings != null && ContainerUtil.isEmpty(linkedProjectSettings.getModules())) { + + final Set modulePaths = ContainerUtil.map2Set( + ExternalSystemApiUtil.findAllRecursively(externalProjectInfo.getExternalProjectStructure(), ProjectKeys.MODULE), + new Function, String>() { + @Override + public String fun(DataNode node) { + return node.getData().getLinkedExternalProjectPath(); + } + }); + linkedProjectSettings.setModules(modulePaths); + } } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java index af73a2869dd2..d8fc40562081 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManager.java @@ -27,6 +27,7 @@ import com.intellij.openapi.externalSystem.model.task.TaskData; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import com.intellij.openapi.externalSystem.view.ExternalProjectsViewState; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; @@ -90,11 +91,15 @@ public class ExternalProjectsManager implements PersistentStateComponent { +public class LibraryDataService implements ProjectDataServiceEx { private static final Logger LOG = Logger.getInstance("#" + LibraryDataService.class.getName()); @NotNull public static final NotNullFunction PATH_TO_FILE = new NotNullFunction() { @@ -49,16 +49,9 @@ public class LibraryDataService implements ProjectDataService> toImport, + @NotNull final Project project, + final boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + importData(toImport, project, platformFacade, synchronous); + } + @Override - public void importData(@NotNull Collection> toImport, @NotNull Project project, boolean synchronous) { + public void importData(@NotNull final Collection> toImport, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + final boolean synchronous) { for (DataNode dataNode : toImport) { - importLibrary(dataNode.getData(), project, synchronous); + importLibrary(dataNode.getData(), project, platformFacade, synchronous); } } - public void importLibrary(@NotNull final LibraryData toImport, @NotNull final Project project, boolean synchronous) { + private void importLibrary(@NotNull final LibraryData toImport, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + boolean synchronous) { Map> libraryFiles = prepareLibraryFiles(toImport); - Library library = myProjectStructureHelper.findIdeLibrary(toImport, project); + Library library = platformFacade.findIdeLibrary(toImport, project); if (library != null) { syncPaths(toImport, library, project, synchronous); return; } - importLibrary(toImport.getInternalName(), libraryFiles, project, synchronous); + importLibrary(toImport.getInternalName(), libraryFiles, project, platformFacade, synchronous); } @NotNull @@ -99,16 +105,17 @@ public class LibraryDataService implements ProjectDataService> libraryFiles, - @NotNull final Project project, - boolean synchronous) + private void importLibrary(@NotNull final String libraryName, + @NotNull final Map> libraryFiles, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + boolean synchronous) { ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { @Override public void execute() { // Is assumed to be called from the EDT. - final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project); + final LibraryTable libraryTable = platformFacade.getProjectLibraryTable(project); final LibraryTable.ModifiableModel projectLibraryModel = libraryTable.getModifiableModel(); final Library intellijLibrary; try { @@ -173,14 +180,24 @@ public class LibraryDataService implements ProjectDataService libraries, @NotNull final Project project, boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + removeData(libraries, project, platformFacade, synchronous); + } + + @Override + public void removeData(@NotNull final Collection libraries, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + boolean synchronous) { if (libraries.isEmpty()) { return; } ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { @Override public void execute() { - final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project); + final LibraryTable libraryTable = platformFacade.getProjectLibraryTable(project); final LibraryTable.ModifiableModel model = libraryTable.getModifiableModel(); try { for (Library library : libraries) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java index ed0cbe93c0bf..a7844acf3b25 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java @@ -21,7 +21,6 @@ import com.intellij.openapi.externalSystem.model.Key; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.*; import com.intellij.openapi.externalSystem.service.project.PlatformFacade; -import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper; import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; @@ -51,18 +50,12 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService< private static final Logger LOG = Logger.getInstance("#" + LibraryDependencyDataService.class.getName()); - @NotNull private final PlatformFacade myPlatformFacade; - @NotNull private final ProjectStructureHelper myProjectStructureHelper; @NotNull private final ModuleDataService myModuleManager; @NotNull private final LibraryDataService myLibraryManager; - public LibraryDependencyDataService(@NotNull PlatformFacade platformFacade, - @NotNull ProjectStructureHelper helper, - @NotNull ModuleDataService moduleManager, + public LibraryDependencyDataService(@NotNull ModuleDataService moduleManager, @NotNull LibraryDataService libraryManager) { - myPlatformFacade = platformFacade; - myProjectStructureHelper = helper; myModuleManager = moduleManager; myLibraryManager = libraryManager; } @@ -74,17 +67,20 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService< } @Override - public void importData(@NotNull Collection> toImport, @NotNull Project project, boolean synchronous) { + public void importData(@NotNull Collection> toImport, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { if (toImport.isEmpty()) { return; } Map, List>> byModule = ExternalSystemApiUtil.groupBy(toImport, MODULE); for (Map.Entry, List>> entry : byModule.entrySet()) { - Module module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project); + Module module = platformFacade.findIdeModule(entry.getKey().getData(), project); if (module == null) { myModuleManager.importData(Collections.singleton(entry.getKey()), project, true); - module = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project); + module = platformFacade.findIdeModule(entry.getKey().getData(), project); if (module == null) { LOG.warn(String.format( "Can't import library dependencies %s. Reason: target module (%s) is not found at the ide and can't be imported", @@ -93,18 +89,19 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService< continue; } } - importData(entry.getValue(), module, synchronous); + importData(entry.getValue(), module, platformFacade, synchronous); } } public void importData(@NotNull final Collection> nodesToImport, @NotNull final Module module, + @NotNull final PlatformFacade platformFacade, final boolean synchronous) { ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) { @Override public void execute() { - importMissingProjectLibraries(module, nodesToImport, synchronous); + importMissingProjectLibraries(module, platformFacade, nodesToImport, synchronous); // The general idea is to import all external project library dependencies and module libraries which don't present at the // ide side yet and remove all project library dependencies and module libraries which present at the ide but not at @@ -137,10 +134,11 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService< } } - ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); - final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel(); + //ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + //final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel(); + final ModifiableRootModel moduleRootModel = ModifiableModelsProvider.SERVICE.getInstance().getModuleModifiableModel(module); LibraryTable moduleLibraryTable = moduleRootModel.getModuleLibraryTable(); - LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject()); + LibraryTable libraryTable = platformFacade.getProjectLibraryTable(module.getProject()); try { syncExistingAndRemoveObsolete(moduleLibrariesToImport, projectLibrariesToImport, toImport, moduleRootModel, hasUnresolved); @@ -258,10 +256,11 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService< } private void importMissingProjectLibraries(@NotNull Module module, + @NotNull PlatformFacade platformFacade, @NotNull Collection> nodesToImport, boolean synchronous) { - LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject()); + LibraryTable libraryTable = platformFacade.getProjectLibraryTable(module.getProject()); List> librariesToImport = ContainerUtilRt.newArrayList(); for (DataNode dataNode : nodesToImport) { final LibraryDependencyData dependencyData = dataNode.getData(); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java index 32919794eca4..cd37c81d10a6 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java @@ -2,6 +2,7 @@ package com.intellij.openapi.externalSystem.service.project.manage; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.Key; @@ -9,7 +10,7 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper; +import com.intellij.openapi.externalSystem.service.project.PlatformFacade; import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; @@ -38,7 +39,7 @@ import java.util.concurrent.TimeUnit; * @since 2/7/12 2:49 PM */ @Order(ExternalSystemConstants.BUILTIN_SERVICE_ORDER) -public class ModuleDataService implements ProjectDataService { +public class ModuleDataService implements ProjectDataServiceEx { public static final com.intellij.openapi.util.Key MODULE_DATA_KEY = com.intellij.openapi.util.Key.create("MODULE_DATA_KEY"); @@ -52,12 +53,6 @@ public class ModuleDataService implements ProjectDataService private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD); - @NotNull private final ProjectStructureHelper myProjectStructureHelper; - - public ModuleDataService(@NotNull ProjectStructureHelper helper) { - myProjectStructureHelper = helper; - } - @NotNull @Override public Key getTargetDataKey() { @@ -66,8 +61,16 @@ public class ModuleDataService implements ProjectDataService public void importData(@NotNull final Collection> toImport, @NotNull final Project project, - final boolean synchronous) - { + final boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + importData(toImport, project, platformFacade, synchronous); + } + + @Override + public void importData(@NotNull final Collection> toImport, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + final boolean synchronous) { if (toImport.isEmpty()) { return; } @@ -78,40 +81,40 @@ public class ModuleDataService implements ProjectDataService ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { @Override public void execute() { - final Collection> toCreate = filterExistingModules(toImport, project); + final Collection> toCreate = filterExistingModules(toImport, project, platformFacade); if (!toCreate.isEmpty()) { - createModules(toCreate, project); + createModules(toCreate, project, platformFacade); } for (DataNode node : toImport) { - Module module = myProjectStructureHelper.findIdeModule(node.getData(), project); + Module module = platformFacade.findIdeModule(node.getData(), project); if (module != null) { - syncPaths(module, node.getData()); + syncPaths(module, platformFacade, node.getData()); } - } + } } }); } - private void createModules(@NotNull final Collection> toCreate, @NotNull final Project project) { + private void createModules(@NotNull final Collection> toCreate, + @NotNull final Project project, + @NotNull final PlatformFacade platformFacade) { removeExistingModulesConfigs(toCreate, project); Application application = ApplicationManager.getApplication(); final Map, Module> moduleMappings = ContainerUtilRt.newHashMap(); application.runWriteAction(new Runnable() { @Override public void run() { - final ModuleManager moduleManager = ModuleManager.getInstance(project); for (DataNode module : toCreate) { - importModule(moduleManager, module); + importModule(module); } } - private void importModule(@NotNull ModuleManager moduleManager, @NotNull DataNode module) { + private void importModule(@NotNull DataNode module) { ModuleData data = module.getData(); - final Module created = moduleManager.newModule(data.getModuleFilePath(), data.getModuleTypeId()); + final Module created = platformFacade.newModule(project, data.getModuleFilePath(), data.getModuleTypeId()); // Ensure that the dependencies are clear (used to be not clear when manually removing the module and importing it via gradle) - final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(created); - final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel(); + final ModifiableRootModel moduleRootModel = platformFacade.getModuleModifiableModel(created); moduleRootModel.inheritSdk(); setModuleOptions(created, module); @@ -142,13 +145,13 @@ public class ModuleDataService implements ProjectDataService } @NotNull - private Collection> filterExistingModules(@NotNull Collection> modules, - @NotNull Project project) + private static Collection> filterExistingModules(@NotNull Collection> modules, + @NotNull Project project, @NotNull PlatformFacade platformFacade) { Collection> result = ContainerUtilRt.newArrayList(); for (DataNode node : modules) { ModuleData moduleData = node.getData(); - Module module = myProjectStructureHelper.findIdeModule(moduleData, project); + Module module = platformFacade.findIdeModule(moduleData, project); if (module == null) { result.add(node); } @@ -184,8 +187,8 @@ public class ModuleDataService implements ProjectDataService }); } - private static void syncPaths(@NotNull Module module, @NotNull ModuleData data) { - ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel(); + private static void syncPaths(@NotNull Module module, @NotNull PlatformFacade platformFacade, @NotNull ModuleData data) { + ModifiableRootModel modifiableModel = platformFacade.getModuleModifiableModel(module); CompilerModuleExtension extension = modifiableModel.getModuleExtension(CompilerModuleExtension.class); if (extension == null) { modifiableModel.dispose(); @@ -209,9 +212,21 @@ public class ModuleDataService implements ProjectDataService modifiableModel.commit(); } } - + @Override - public void removeData(@NotNull final Collection modules, @NotNull Project project, boolean synchronous) { + public void removeData(@NotNull Collection toRemove, + @NotNull Project project, + boolean synchronous) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + removeData(toRemove, project, platformFacade, synchronous); + } + + + @Override + public void removeData(@NotNull final Collection modules, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { if (modules.isEmpty()) { return; } @@ -219,7 +234,7 @@ public class ModuleDataService implements ProjectDataService @Override public void execute() { for (Module module : modules) { - if(module.isDisposed()) continue; + if (module.isDisposed()) continue; ModuleManager moduleManager = ModuleManager.getInstance(module.getProject()); String path = module.getModuleFilePath(); @@ -241,7 +256,7 @@ public class ModuleDataService implements ProjectDataService module.clearOption(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY); module.clearOption(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY); } - + private class ImportModulesTask implements Runnable { private final Project myProject; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java index f8e368afa106..d9ee6c4aca98 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDependencyDataService.java @@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.ModuleData; import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper; +import com.intellij.openapi.externalSystem.service.project.PlatformFacade; import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; @@ -51,11 +51,9 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService> toImport, @NotNull Project project, boolean synchronous) { + public void importData(@NotNull Collection> toImport, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { Map, List>> byModule= ExternalSystemApiUtil.groupBy(toImport, MODULE); for (Map.Entry, List>> entry : byModule.entrySet()) { - Module ideModule = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project); + Module ideModule = platformFacade.findIdeModule(entry.getKey().getData(), project); if (ideModule == null) { myModuleDataManager.importData(Collections.singleton(entry.getKey()), project, true); - ideModule = myProjectStructureHelper.findIdeModule(entry.getKey().getData(), project); + ideModule = platformFacade.findIdeModule(entry.getKey().getData(), project); } if (ideModule == null) { LOG.warn(String.format( @@ -81,13 +82,14 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService> toImport, - @NotNull final Module module, - final boolean synchronous) + private void importData(@NotNull final Collection> toImport, + @NotNull final Module module, + @NotNull final PlatformFacade platformFacade, + final boolean synchronous) { ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(module) { @Override @@ -100,19 +102,18 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService dependencyNode : toImport) { final ModuleDependencyData dependencyData = dependencyNode.getData(); toRemove.remove(Pair.create(dependencyData.getInternalName(), dependencyData.getScope())); final String moduleName = dependencyData.getInternalName(); - Module ideDependencyModule = myProjectStructureHelper.findIdeModule(moduleName, module.getProject()); + Module ideDependencyModule = platformFacade.findIdeModule(moduleName, module.getProject()); if (ideDependencyModule == null) { DataNode projectNode = dependencyNode.getDataNode(ProjectKeys.PROJECT); if (projectNode != null) { - DataNode n - = ExternalSystemApiUtil.find(projectNode, MODULE, new BooleanFunction>() { + DataNode n = ExternalSystemApiUtil.find(projectNode, MODULE, new BooleanFunction>() { @Override public boolean fun(DataNode node) { return node.getData().equals(dependencyData.getTarget()); @@ -120,7 +121,7 @@ public class ModuleDependencyDataService extends AbstractDependencyDataService, List>>> myServices; + private final PlatformFacade myPlatformFacade; public static ProjectDataManager getInstance() { return ServiceManager.getService(ProjectDataManager.class); } - public ProjectDataManager() { + public ProjectDataManager(@NotNull PlatformFacade platformFacade) { myServices = new NotNullLazyValue, List>>>() { @NotNull @Override @@ -72,6 +75,7 @@ public class ProjectDataManager { return result; } }; + myPlatformFacade = platformFacade; } @Nullable @@ -82,7 +86,10 @@ public class ProjectDataManager { } @SuppressWarnings("unchecked") - public void importData(@NotNull Collection> nodes, @NotNull Project project, boolean synchronous) { + public void importData(@NotNull Collection> nodes, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { if (project.isDisposed()) return; Map, List>> grouped = ExternalSystemApiUtil.group(nodes); @@ -92,12 +99,20 @@ public class ProjectDataManager { for (DataNode node : entry.getValue()) { dummy.add((DataNode)node); } - importData((Key)entry.getKey(), dummy, project, synchronous); + importData((Key)entry.getKey(), dummy, project, platformFacade, synchronous); } } + public void importData(@NotNull Collection> nodes, @NotNull Project project, boolean synchronous) { + importData(nodes, project, myPlatformFacade, synchronous); + } + @SuppressWarnings("unchecked") - public void importData(@NotNull Key key, @NotNull Collection> nodes, @NotNull Project project, boolean synchronous) { + public void importData(@NotNull Key key, + @NotNull Collection> nodes, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous) { if (project.isDisposed()) return; ensureTheDataIsReadyToUse((Collection)nodes); @@ -110,7 +125,12 @@ public class ProjectDataManager { } else { for (ProjectDataService service : services) { - ((ProjectDataService)service).importData(nodes, project, synchronous); + if (service instanceof ProjectDataServiceEx) { + ((ProjectDataServiceEx)service).importData(nodes, project, platformFacade, synchronous); + } + else { + ((ProjectDataService)service).importData(nodes, project, synchronous); + } } } @@ -118,7 +138,14 @@ public class ProjectDataManager { for (DataNode node : nodes) { children.addAll(node.getChildren()); } - importData(children, project, synchronous); + importData(children, project, platformFacade, synchronous); + } + + public void importData(@NotNull Key key, + @NotNull Collection> nodes, + @NotNull Project project, + boolean synchronous) { + importData(key, nodes, project, myPlatformFacade, synchronous); } public void ensureTheDataIsReadyToUse(DataNode dataNode) { @@ -129,7 +156,7 @@ public class ProjectDataManager { List> services = servicesByKey.get(dataNode.getKey()); if (services != null) { try { - dataNode.prepareData(ContainerUtil.map2Array(services, ClassLoader.class, new Function, ClassLoader>() { + dataNode.prepareData(map2Array(services, ClassLoader.class, new Function, ClassLoader>() { @Override public ClassLoader fun(ProjectDataService service) { return service.getClass().getClassLoader(); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataServiceEx.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataServiceEx.java new file mode 100644 index 000000000000..2f76ef49936a --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ProjectDataServiceEx.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.externalSystem.service.project.manage; + +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.service.project.PlatformFacade; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * @author Vladislav.Soroka + * @since 4/13/2015 + */ +public interface ProjectDataServiceEx extends ProjectDataService { + + void importData(@NotNull Collection> toImport, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous); + + void removeData(@NotNull Collection toRemove, + @NotNull Project project, + @NotNull PlatformFacade platformFacade, + boolean synchronous); +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index c1e04c1af862..89bcd432bff0 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -1,17 +1,20 @@ package com.intellij.openapi.externalSystem.service.project.wizard; import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener; import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; -import com.intellij.openapi.externalSystem.service.internal.ExternalSystemResolveProjectTask; import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; +import com.intellij.openapi.externalSystem.service.project.PlatformFacade; +import com.intellij.openapi.externalSystem.service.project.PlatformFacadeImpl; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; @@ -22,30 +25,28 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; -import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; -import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.packaging.artifacts.ModifiableArtifactModel; import com.intellij.projectImport.ProjectImportBuilder; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; -import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; /** * GoF builder for gradle-backed projects. @@ -77,7 +78,7 @@ public abstract class AbstractExternalProjectImportBuilder> getList() { - return Arrays.asList(myExternalProjectNode); + return Collections.singletonList(myExternalProjectNode); } @Override @@ -100,6 +101,7 @@ public abstract class AbstractExternalProjectImportBuilder commit(final Project project, - ModifiableModuleModel model, - ModulesProvider modulesProvider, - ModifiableArtifactModel artifactModel) + final ModifiableModuleModel model, + final ModulesProvider modulesProvider, + final ModifiableArtifactModel artifactModel) { project.putUserData(ExternalSystemDataKeys.NEWLY_IMPORTED_PROJECT, Boolean.TRUE); final DataNode externalProjectNode = getExternalProjectNode(); if (externalProjectNode != null) { beforeCommit(externalProjectNode, project); } - StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { - @SuppressWarnings("unchecked") + + boolean isFromUI = model != null; + + final List modules = ContainerUtil.newSmartList(); + final PlatformFacade platformFacade = isFromUI ? new PlatformFacadeImpl() { + @NotNull @Override - public void run() { - AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(project, myExternalSystemId); - final ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings(); - Set projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings()); - // add current importing project settings to linked projects settings or replace if similar already exist - projects.remove(projectSettings); - projects.add(projectSettings); + public Collection getModules(@NotNull Project project) { + return ContainerUtil.list(modulesProvider.getModules()); + } - systemSettings.copyFrom(myControl.getSystemSettings()); - systemSettings.setLinkedProjectsSettings(projects); + @Override + public Module newModule(Project project, @NotNull @NonNls String filePath, String moduleTypeId) { + final Module module = model.newModule(filePath, moduleTypeId); + modules.add(module); + return module; + } + } : ServiceManager.getService(PlatformFacade.class); + AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(project, myExternalSystemId); + final ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings(); - if (externalProjectNode != null) { - ExternalSystemUtil.ensureToolWindowInitialized(project, myExternalSystemId); - ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) { - @Override - public void execute() { - ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() { - @Override - public void run() { - myProjectDataManager.importData(externalProjectNode.getKey(), Collections.singleton(externalProjectNode), project, true); - myExternalProjectNode = null; - } - }); - } - }); + //noinspection unchecked + Set projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings()); + // add current importing project settings to linked projects settings or replace if similar already exist + projects.remove(projectSettings); + projects.add(projectSettings); - final Runnable resolveDependenciesTask = new Runnable() { + //noinspection unchecked + systemSettings.copyFrom(myControl.getSystemSettings()); + //noinspection unchecked + systemSettings.setLinkedProjectsSettings(projects); + + if (externalProjectNode != null) { + ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) { + @Override + public void execute() { + ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() { @Override public void run() { - String progressText = ExternalSystemBundle.message("progress.resolve.libraries", myExternalSystemId.getReadableName()); - ProgressManager.getInstance().run( - new Task.Backgroundable(project, progressText, false) { - @Override - public void run(@NotNull final ProgressIndicator indicator) { - if(project.isDisposed()) return; - ExternalSystemResolveProjectTask task - = new ExternalSystemResolveProjectTask(myExternalSystemId, project, projectSettings.getExternalProjectPath(), false); - task.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions()); - DataNode projectWithResolvedLibraries = task.getExternalProject(); - if (projectWithResolvedLibraries == null) { - return; - } - - setupLibraries(projectWithResolvedLibraries, project); - } - }); + myProjectDataManager.importData( + externalProjectNode.getKey(), Collections.singleton(externalProjectNode), project, platformFacade, true); + myExternalProjectNode = null; } - }; - UIUtil.invokeLaterIfNeeded(resolveDependenciesTask); + }); } + }); + + // resolve dependencies + final Runnable resolveDependenciesTask = new Runnable() { + @Override + public void run() { + ExternalSystemUtil.refreshProject( + project, myExternalSystemId, projectSettings.getExternalProjectPath(), false, + ProgressExecutionMode.IN_BACKGROUND_ASYNC); + } + }; + if (!isFromUI) { + resolveDependenciesTask.run(); } - }); - return Collections.emptyList(); + else { + // execute when current dialog is closed + ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, new Runnable() { + @Override + public void run() { + final Module[] committedModules = ModuleManager.getInstance(project).getModules(); + if (ContainerUtil.list(committedModules).containsAll(modules)) { + resolveDependenciesTask.run(); + } + else { + ExternalSystemApiUtil.getLocalSettings(project, myExternalSystemId).forgetExternalProjects( + Collections.singleton(projectSettings.getExternalProjectPath())); + ExternalSystemApiUtil.getSettings(project, myExternalSystemId).unlinkExternalProject( + projectSettings.getExternalProjectPath()); + + ExternalProjectsManager.getInstance(project).forgetExternalProjectData( + myExternalSystemId, projectSettings.getExternalProjectPath()); + } + } + }); + } + } + return modules; } @NotNull @@ -189,62 +217,6 @@ public abstract class AbstractExternalProjectImportBuilder dataNode, @NotNull Project project); - /** - * The whole import sequence looks like below: - *

- *

-   * 
    - *
  1. Get project view from the gradle tooling api without resolving dependencies (downloading libraries);
  2. - *
  3. Allow to adjust project settings before importing;
  4. - *
  5. Create IJ project and modules;
  6. - *
  7. Ask gradle tooling api to resolve library dependencies (download the if necessary);
  8. - *
  9. Configure libraries used by the gradle project at intellij;
  10. - *
  11. Configure library dependencies;
  12. - *
- *
- *

- * - * @param projectWithResolvedLibraries gradle project with resolved libraries (libraries have already been downloaded and - * are available at file system under gradle service directory) - * @param project current intellij project which should be configured by libraries and module library - * dependencies information available at the given gradle project - */ - private void setupLibraries(@NotNull final DataNode projectWithResolvedLibraries, final Project project) { - ExternalSystemApiUtil.executeProjectChangeAction(new DisposeAwareProjectChange(project) { - @Override - public void execute() { - ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() { - @Override - public void run() { - if (ExternalSystemApiUtil.isNewProjectConstruction()) { - // Clean existing libraries (if any). - LibraryTable projectLibraryTable = ProjectLibraryTable.getInstance(project); - if (projectLibraryTable == null) { - LOG.warn( - "Can't resolve external dependencies of the target gradle project (" + project + "). Reason: project " - + "library table is undefined" - ); - return; - } - LibraryTable.ModifiableModel model = projectLibraryTable.getModifiableModel(); - try { - for (Library library : model.getLibraries()) { - model.removeLibrary(library); - } - } - finally { - model.commit(); - } - } - - // Register libraries. - myProjectDataManager.importData(Collections.>singletonList(projectWithResolvedLibraries), project, false); - } - }); - } - }); - } - @Nullable private File getProjectFile() { String path = myControl.getProjectSettings().getExternalProjectPath(); @@ -323,11 +295,6 @@ public abstract class AbstractExternalProjectImportBuilder extends ModuleWizardStep { + public static final Key SKIP_STEP_KEY = Key.create("SKIP_STEP_KEY"); + @NotNull private final AbstractExternalModuleBuilder myExternalModuleBuilder; @NotNull private final AbstractExternalProjectSettingsControl myControl; + @Nullable private final WizardContext myContext; @Nullable private PaintAwarePanel myComponent; - public ExternalModuleSettingsStep(@NotNull AbstractExternalModuleBuilder externalModuleBuilder, @NotNull AbstractExternalProjectSettingsControl control) { + public ExternalModuleSettingsStep(@Nullable WizardContext context, + @NotNull AbstractExternalModuleBuilder externalModuleBuilder, + @NotNull AbstractExternalProjectSettingsControl control) { myExternalModuleBuilder = externalModuleBuilder; myControl = control; + myContext = context; + } + + public ExternalModuleSettingsStep(@NotNull AbstractExternalModuleBuilder externalModuleBuilder, + @NotNull AbstractExternalProjectSettingsControl control) { + this(null, externalModuleBuilder, control); } @Override @@ -83,4 +96,9 @@ public class ExternalModuleSettingsStep exten super.disposeUIResources(); myControl.disposeUIResources(); } + + @Override + public boolean isStepVisible() { + return myContext == null || !Boolean.TRUE.equals(myContext.getUserData(SKIP_STEP_KEY)); + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java index deb9a9044ea6..5197481f4519 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java @@ -54,7 +54,7 @@ public abstract class AbstractImportFromExternalSystemControl< @NotNull private final PaintAwarePanel myComponent = new PaintAwarePanel(new GridBagLayout()); @NotNull private final TextFieldWithBrowseButton myLinkedProjectPathField = new TextFieldWithBrowseButton(); @Nullable private final HideableTitledPanel hideableSystemSettingsPanel; - @Nullable private final ProjectFormatPanel myProjectFormatPanel; + @NotNull private final ProjectFormatPanel myProjectFormatPanel; @NotNull private final ExternalSystemSettingsControl myProjectSettingsControl; @NotNull private final ProjectSystemId myExternalSystemId; @@ -62,6 +62,9 @@ public abstract class AbstractImportFromExternalSystemControl< @Nullable Project myCurrentProject; + private boolean myShowProjectFormatPanel; + private final JLabel myProjectFormatLabel; + protected AbstractImportFromExternalSystemControl(@NotNull ProjectSystemId externalSystemId, @NotNull SystemSettings systemSettings, @NotNull ProjectSettings projectSettings) @@ -80,6 +83,7 @@ public abstract class AbstractImportFromExternalSystemControl< myProjectSettings = projectSettings; myProjectSettingsControl = createProjectSettingsControl(projectSettings); mySystemSettingsControl = createSystemSettingsControl(systemSettings); + myShowProjectFormatPanel = showProjectFormatPanel; JLabel linkedProjectPathLabel = new JLabel(ExternalSystemBundle.message("settings.label.select.project", externalSystemId.getReadableName())); @@ -115,14 +119,10 @@ public abstract class AbstractImportFromExternalSystemControl< myComponent.add(myLinkedProjectPathField, ExternalSystemUiUtil.getFillLineConstraints(0)); myProjectSettingsControl.fillUi(myComponent, 0); - if(showProjectFormatPanel) { - myProjectFormatPanel = new ProjectFormatPanel(); - JLabel myProjectFormatLabel = new JLabel(ExternalSystemBundle.message("settings.label.project.format")); - myComponent.add(myProjectFormatLabel, ExternalSystemUiUtil.getLabelConstraints(0)); - myComponent.add(myProjectFormatPanel.getStorageFormatComboBox(), ExternalSystemUiUtil.getFillLineConstraints(0)); - } else { - myProjectFormatPanel = null; - } + myProjectFormatPanel = new ProjectFormatPanel(); + myProjectFormatLabel = new JLabel(ExternalSystemBundle.message("settings.label.project.format")); + myComponent.add(myProjectFormatLabel, ExternalSystemUiUtil.getLabelConstraints(0)); + myComponent.add(myProjectFormatPanel.getStorageFormatComboBox(), ExternalSystemUiUtil.getFillLineConstraints(0)); if (mySystemSettingsControl != null) { final PaintAwarePanel mySystemSettingsControlPanel = new PaintAwarePanel(); @@ -213,6 +213,10 @@ public abstract class AbstractImportFromExternalSystemControl< return myProjectSettings; } + public void setShowProjectFormatPanel(boolean showProjectFormatPanel) { + myShowProjectFormatPanel = showProjectFormatPanel; + } + public void reset() { myLinkedProjectPathField.setText(""); myProjectSettingsControl.reset(); @@ -222,6 +226,10 @@ public abstract class AbstractImportFromExternalSystemControl< if (hideableSystemSettingsPanel != null) { hideableSystemSettingsPanel.setOn(false); } + myProjectFormatLabel.setVisible(myShowProjectFormatPanel); + myProjectFormatPanel.setVisible(myShowProjectFormatPanel); + myProjectFormatPanel.getPanel().setVisible(myShowProjectFormatPanel); + myProjectFormatPanel.getStorageFormatComboBox().setVisible(myShowProjectFormatPanel); } public void apply() throws ConfigurationException { @@ -252,6 +260,6 @@ public abstract class AbstractImportFromExternalSystemControl< @Nullable public ProjectFormatPanel getProjectFormatPanel() { - return myProjectFormatPanel; + return myShowProjectFormatPanel ? myProjectFormatPanel : null; } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java index d6ec2d53159e..49f5d05c0609 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/AbstractExternalSystemToolWindowFactory.java @@ -18,7 +18,7 @@ package com.intellij.openapi.externalSystem.service.task.ui; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; -import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; @@ -44,7 +44,7 @@ public abstract class AbstractExternalSystemToolWindowFactory implements ToolWin public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) { toolWindow.setTitle(myExternalSystemId.getReadableName()); ContentManager contentManager = toolWindow.getContentManager(); - final ExternalProjectsView projectsView = new ExternalProjectsView(project, (ToolWindowEx)toolWindow, myExternalSystemId); + final ExternalProjectsViewImpl projectsView = new ExternalProjectsViewImpl(project, (ToolWindowEx)toolWindow, myExternalSystemId); ExternalProjectsManager.getInstance(project).registerView(projectsView); ContentImpl tasksContent = new ContentImpl(projectsView, ExternalSystemBundle.message("tool.window.title.projects"), true); contentManager.addContent(tasksContent); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java index 80af1b886051..70b0deeb0799 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalToolWindowManager.java @@ -5,7 +5,10 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; +import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.impl.ToolWindowImpl; @@ -41,6 +44,25 @@ public class ExternalToolWindowManager { if (toolWindow != null) { toolWindow.setAvailable(true, null); } + else { + StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { + @Override + public void run() { + if (project.isDisposed()) return; + + ExternalSystemUtil.ensureToolWindowInitialized(project, manager.getSystemId()); + ToolWindowManager.getInstance(project).invokeLater(new Runnable() { + public void run() { + if (project.isDisposed()) return; + ToolWindow toolWindow = getToolWindow(project, manager.getSystemId()); + if (toolWindow != null) { + toolWindow.setAvailable(true, null); + } + } + }); + } + }); + } } @Override @@ -53,7 +75,7 @@ public class ExternalToolWindowManager { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { - toolWindow.setAvailable(false, null); + toolWindow.setAvailable(false, null); } }); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java index dffc648648d2..04059e31ab5e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java @@ -26,8 +26,6 @@ import com.intellij.execution.rmi.RemoteUtil; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.DataKey; -import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.ServiceManager; @@ -62,6 +60,7 @@ import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettin import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.task.TaskCallback; import com.intellij.openapi.externalSystem.view.ExternalProjectsView; +import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.PerformInBackgroundOption; import com.intellij.openapi.progress.ProgressIndicator; @@ -88,9 +87,8 @@ import com.intellij.openapi.wm.impl.ToolWindowImpl; import com.intellij.ui.CheckBoxList; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.components.JBScrollPane; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentManager; import com.intellij.util.Consumer; +import com.intellij.util.DisposeAwareRunnable; import com.intellij.util.Function; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; @@ -126,57 +124,27 @@ public class ExternalSystemUtil { } public static void ensureToolWindowInitialized(@NotNull Project project, @NotNull ProjectSystemId externalSystemId) { - ToolWindowManager manager = ToolWindowManager.getInstance(project); - if (!(manager instanceof ToolWindowManagerEx)) { - return; - } - ToolWindowManagerEx managerEx = (ToolWindowManagerEx)manager; - String id = externalSystemId.getReadableName(); - ToolWindow window = manager.getToolWindow(id); - if (window != null) { - return; - } - ToolWindowEP[] beans = Extensions.getExtensions(ToolWindowEP.EP_NAME); - for (final ToolWindowEP bean : beans) { - if (id.equals(bean.id)) { - managerEx.initToolWindow(bean); + try { + ToolWindowManager manager = ToolWindowManager.getInstance(project); + if (!(manager instanceof ToolWindowManagerEx)) { + return; } - } - } - - @Nullable - public static T getToolWindowElement(@NotNull Class clazz, - @NotNull Project project, - @NotNull DataKey key, - @NotNull ProjectSystemId externalSystemId) { - if (project.isDisposed() || !project.isOpen()) { - return null; - } - final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project); - if (toolWindowManager == null) { - return null; - } - final ToolWindow toolWindow = ensureToolWindowContentInitialized(project, externalSystemId); - if (toolWindow == null) { - return null; - } - - final ContentManager contentManager = toolWindow.getContentManager(); - if (contentManager == null) { - return null; - } - - for (Content content : contentManager.getContents()) { - final JComponent component = content.getComponent(); - if (component instanceof DataProvider) { - final Object data = ((DataProvider)component).getData(key.getName()); - if (data != null && clazz.isInstance(data)) { - //noinspection unchecked - return (T)data; + ToolWindowManagerEx managerEx = (ToolWindowManagerEx)manager; + String id = externalSystemId.getReadableName(); + ToolWindow window = manager.getToolWindow(id); + if (window != null) { + return; + } + ToolWindowEP[] beans = Extensions.getExtensions(ToolWindowEP.EP_NAME); + for (final ToolWindowEP bean : beans) { + if (id.equals(bean.id)) { + managerEx.initToolWindow(bean); } } } - return null; + catch (Exception e) { + LOG.error(String.format("Unable to initialize %s tool window", externalSystemId.getReadableName()), e); + } } @Nullable @@ -201,7 +169,7 @@ public class ExternalSystemUtil { * @param project target ide project * @param externalSystemId target external system which projects should be refreshed * @param force flag which defines if external project refresh should be performed if it's config is up-to-date - * @deprecated use {@link ExternalSystemUtil#refreshProjects(com.intellij.openapi.externalSystem.importing.ImportSpecBuilder)} + * @deprecated use {@link ExternalSystemUtil#refreshProjects(ImportSpecBuilder)} */ @Deprecated public static void refreshProjects(@NotNull final Project project, @NotNull final ProjectSystemId externalSystemId, boolean force) { @@ -217,7 +185,7 @@ public class ExternalSystemUtil { * @param externalSystemId target external system which projects should be refreshed * @param force flag which defines if external project refresh should be performed if it's config is up-to-date * - * @deprecated use {@link ExternalSystemUtil#refreshProjects(com.intellij.openapi.externalSystem.importing.ImportSpecBuilder)} + * @deprecated use {@link ExternalSystemUtil#refreshProjects(ImportSpecBuilder)} */ @Deprecated public static void refreshProjects(@NotNull final Project project, @NotNull final ProjectSystemId externalSystemId, boolean force, @NotNull final ProgressExecutionMode progressExecutionMode) { @@ -399,8 +367,51 @@ public class ExternalSystemUtil { return null; } + public static void refreshProject(@NotNull final Project project, + @NotNull final ProjectSystemId externalSystemId, + @NotNull final String externalProjectPath, + final boolean isPreviewMode, + @NotNull final ProgressExecutionMode progressExecutionMode) { + final PlatformFacade platformFacade = ServiceManager.getService(PlatformFacade.class); + refreshProject(project, platformFacade, externalSystemId, externalProjectPath, isPreviewMode, progressExecutionMode); + } + + public static void refreshProject(@NotNull final Project project, + @NotNull final PlatformFacade platformFacade, + @NotNull final ProjectSystemId externalSystemId, + @NotNull final String externalProjectPath, + final boolean isPreviewMode, + @NotNull final ProgressExecutionMode progressExecutionMode) { + refreshProject(project, externalSystemId, externalProjectPath, new ExternalProjectRefreshCallback() { + @Override + public void onSuccess(@Nullable final DataNode externalProject) { + if (externalProject == null) { + return; + } + final boolean synchronous = progressExecutionMode == ProgressExecutionMode.MODAL_SYNC; + ExternalSystemApiUtil.executeProjectChangeAction(synchronous, new DisposeAwareProjectChange(project) { + @Override + public void execute() { + ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() { + @Override + public void run() { + final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class); + projectDataManager + .importData(externalProject.getKey(), Collections.singleton(externalProject), project, platformFacade, synchronous); + } + }); + } + }); + } + + @Override + public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) { + } + }, isPreviewMode, progressExecutionMode, true); + } + /** - * TODO[Vlad]: refactor the method to use {@link com.intellij.openapi.externalSystem.importing.ImportSpecBuilder} + * TODO[Vlad]: refactor the method to use {@link ImportSpecBuilder} * * Queries slave gradle process to refresh target gradle project. * @@ -420,7 +431,7 @@ public class ExternalSystemUtil { } /** - * TODO[Vlad]: refactor the method to use {@link com.intellij.openapi.externalSystem.importing.ImportSpecBuilder} + * TODO[Vlad]: refactor the method to use {@link ImportSpecBuilder} * * Queries slave gradle process to refresh target gradle project. * @@ -916,8 +927,8 @@ public class ExternalSystemUtil { public static void scheduleExternalViewStructureUpdate(final Project project, final ProjectSystemId systemId) { ExternalProjectsView externalProjectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(systemId); - if (externalProjectsView != null) { - externalProjectsView.scheduleStructureUpdate(); + if (externalProjectsView instanceof ExternalProjectsViewImpl) { + ((ExternalProjectsViewImpl)externalProjectsView).scheduleStructureUpdate(); } } @@ -934,6 +945,24 @@ public class ExternalSystemUtil { } + public static void invokeLater(Project p, Runnable r) { + invokeLater(p, ModalityState.defaultModalityState(), r); + } + + public static void invokeLater(final Project p, final ModalityState state, final Runnable r) { + if (isNoBackgroundMode()) { + r.run(); + } + else { + ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state); + } + } + + public static boolean isNoBackgroundMode() { + return (ApplicationManager.getApplication().isUnitTestMode() + || ApplicationManager.getApplication().isHeadlessEnvironment()); + } + private interface TaskUnderProgress { void execute(@NotNull ProgressIndicator indicator); } @@ -1012,9 +1041,7 @@ public class ExternalSystemUtil { if (externalSystemIdAsString.equals(s) && !myExternalModulePaths.contains(p)) { orphanIdeModules.add(module); if(ExternalSystemDebugEnvironment.DEBUG_ORPHAN_MODULES_PROCESSING) { - LOG.info(String.format( - "External paths doesn't contain IDE module LINKED_PROJECT_PATH_KEY anymore => add to orphan IDE modules." - )); + LOG.info("External paths doesn't contain IDE module LINKED_PROJECT_PATH_KEY anymore => add to orphan IDE modules."); } } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsStructure.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsStructure.java index 0eb2d5e81614..9e99af4d9836 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsStructure.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsStructure.java @@ -19,11 +19,9 @@ import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; -import com.intellij.ui.treeStructure.SimpleNode; -import com.intellij.ui.treeStructure.SimpleTree; -import com.intellij.ui.treeStructure.SimpleTreeBuilder; -import com.intellij.ui.treeStructure.SimpleTreeStructure; +import com.intellij.ui.treeStructure.*; import com.intellij.util.Consumer; +import com.intellij.util.Function; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; @@ -42,21 +40,23 @@ import java.util.Map; */ public class ExternalProjectsStructure extends SimpleTreeStructure { private final Project myProject; - private final ExternalProjectsView myExternalProjectsView; + private ExternalProjectsView myExternalProjectsView; private final SimpleTreeBuilder myTreeBuilder; - private final RootNode myRoot; + private RootNode myRoot; private final Map myNodeMapping = new THashMap(); - public ExternalProjectsStructure(Project project, ExternalProjectsView externalProjectsView, SimpleTree tree) { + public ExternalProjectsStructure(Project project, SimpleTree tree) { myProject = project; - myExternalProjectsView = externalProjectsView; configureTree(tree); myTreeBuilder = new SimpleTreeBuilder(tree, (DefaultTreeModel)tree.getModel(), this, null); Disposer.register(myProject, myTreeBuilder); + } + public void init(ExternalProjectsView externalProjectsView) { + myExternalProjectsView = externalProjectsView; myRoot = new RootNode(); myTreeBuilder.initRoot(); myTreeBuilder.expand(myRoot, null); @@ -66,11 +66,11 @@ public class ExternalProjectsStructure extends SimpleTreeStructure { return myProject; } - void updateFrom(SimpleNode node) { + public void updateFrom(SimpleNode node) { myTreeBuilder.addSubtreeToUpdateByElement(node); } - void updateUpTo(SimpleNode node) { + public void updateUpTo(SimpleNode node) { SimpleNode each = node; while (each != null) { updateFrom(each); @@ -88,16 +88,40 @@ public class ExternalProjectsStructure extends SimpleTreeStructure { tree.setShowsRootHandles(true); } + public void accept(@NotNull SimpleNodeVisitor visitor) { + if (myTreeBuilder.getTree() instanceof SimpleTree) { + ((SimpleTree)myTreeBuilder.getTree()).accept(myTreeBuilder, visitor); + } + } + + public void select(SimpleNode node) { + myTreeBuilder.select(node, null); + } + + protected Class[] getVisibleNodesClasses() { + return null; + } + public void updateProjects(Collection> toImport) { + List orphanProjects = ContainerUtil.mapNotNull( + myNodeMapping.entrySet(), new Function, String>() { + @Override + public String fun(Map.Entry entry) { + return entry.getValue() instanceof ProjectNode ? entry.getKey() : null; + } + }); for (DataNode each : toImport) { final ProjectData projectData = each.getData(); - ExternalSystemNode projectNode = findNodeFor(projectData.getLinkedExternalProjectPath()); + final String projectPath = projectData.getLinkedExternalProjectPath(); + orphanProjects.remove(projectPath); + + ExternalSystemNode projectNode = findNodeFor(projectPath); if (projectNode instanceof ProjectNode) { doMergeChildrenChanges(projectNode, each, new ProjectNode(myExternalProjectsView, each)); } else { - ExternalSystemNode node = myNodeMapping.remove(projectData.getLinkedExternalProjectPath()); + ExternalSystemNode node = myNodeMapping.remove(projectPath); if (node != null) { SimpleNode parent = node.getParent(); if (parent instanceof ExternalSystemNode) { @@ -106,13 +130,25 @@ public class ExternalProjectsStructure extends SimpleTreeStructure { } projectNode = new ProjectNode(myExternalProjectsView, each); - myNodeMapping.put(projectData.getLinkedExternalProjectPath(), projectNode); + myNodeMapping.put(projectPath, projectNode); } if (toImport.size() == 0) { myTreeBuilder.expand(projectNode, null); } doUpdateProject((ProjectNode)projectNode); } + + //remove orphan projects from view + for (String orphanProjectPath : orphanProjects) { + ExternalSystemNode projectNode = myNodeMapping.remove(orphanProjectPath); + if (projectNode instanceof ProjectNode) { + SimpleNode parent = projectNode.getParent(); + if (parent instanceof ExternalSystemNode) { + ((ExternalSystemNode)parent).remove(projectNode); + updateUpTo(projectNode); + } + } + } } private void doMergeChildrenChanges(ExternalSystemNode currentNode, DataNode newDataNode, ExternalSystemNode newNode) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsView.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsView.java index 96696e756a60..56e1c622d2d0 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsView.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsView.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,602 +15,40 @@ */ package com.intellij.openapi.externalSystem.view; -import com.intellij.execution.*; -import com.intellij.ide.util.treeView.TreeState; -import com.intellij.notification.NotificationGroup; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.ExternalSystemUiAware; -import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction; -import com.intellij.openapi.externalSystem.model.*; -import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo; -import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.model.task.TaskData; -import com.intellij.openapi.externalSystem.service.execution.ExternalSystemTaskLocation; -import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager; import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; -import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; -import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; -import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.SimpleToolWindowPanel; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.ex.ToolWindowEx; -import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; -import com.intellij.openapi.wm.ex.ToolWindowManagerEx; -import com.intellij.openapi.wm.impl.ToolWindowImpl; -import com.intellij.pom.Navigatable; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiFileFactory; -import com.intellij.ui.PopupHandler; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.treeStructure.SimpleTree; -import com.intellij.util.Consumer; -import com.intellij.util.DisposeAwareRunnable; -import com.intellij.util.Function; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.MultiMap; -import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.tree.TreeSelectionModel; -import java.awt.*; -import java.util.*; import java.util.List; /** * @author Vladislav.Soroka - * @since 9/19/2014 + * @since 4/15/2015 */ -public class ExternalProjectsView extends SimpleToolWindowPanel implements DataProvider { - public static final Logger LOG = Logger.getInstance(ExternalProjectsView.class); - - @NotNull - private final Project myProject; - @NotNull - private final ExternalProjectsManager myProjectsManager; - @NotNull - private final ToolWindowEx myToolWindow; - @NotNull - private final ProjectSystemId myExternalSystemId; - @NotNull - private final ExternalSystemUiAware myUiAware; +public interface ExternalProjectsView { + ExternalSystemUiAware getUiAware(); @Nullable - private ExternalProjectsStructure myStructure; - private SimpleTree myTree; - @NotNull - private final NotificationGroup myNotificationGroup; + ExternalProjectsStructure getStructure(); - private ExternalProjectsViewState myState = new ExternalProjectsViewState(); + ExternalSystemShortcutsManager getShortcutsManager(); - public ExternalProjectsView(@NotNull Project project, @NotNull ToolWindowEx toolWindow, @NotNull ProjectSystemId externalSystemId) { - super(true, true); - myProject = project; - myToolWindow = toolWindow; - myExternalSystemId = externalSystemId; - myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); - myProjectsManager = ExternalProjectsManager.getInstance(myProject); + ExternalSystemTaskActivator getTaskActivator(); - String toolWindowId = - toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : myExternalSystemId.getReadableName(); + void updateUpTo(ExternalSystemNode node); - String notificationId = "notification.group.id." + externalSystemId.getId().toLowerCase(Locale.ENGLISH); - NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationId); - myNotificationGroup = registeredGroup != null ? registeredGroup : NotificationGroup.toolWindowGroup(notificationId, toolWindowId); - } + List> createNodes(@NotNull ExternalProjectsView externalProjectsView, @Nullable ExternalSystemNode parent, @NotNull DataNode dataNode); - @Nullable - @Override - public Object getData(@NonNls String dataId) { - if (ExternalSystemDataKeys.VIEW.is(dataId)) return this; + Project getProject(); - if (PlatformDataKeys.HELP_ID.is(dataId)) return "reference.toolwindows.gradle"; - if (CommonDataKeys.PROJECT.is(dataId)) return myProject; - if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) return extractVirtualFile(); - if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return extractVirtualFiles(); - if (Location.DATA_KEY.is(dataId)) { - return extractLocation(); - } - if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) return extractNavigatables(); + boolean showInheritedTasks(); - if (ExternalSystemDataKeys.EXTERNAL_SYSTEM_ID.is(dataId)) return myExternalSystemId; - if (ExternalSystemDataKeys.UI_AWARE.is(dataId)) return myUiAware; - if (ExternalSystemDataKeys.SELECTED_PROJECT_NODE.is(dataId)) return getSelectedProjectNode(); - if (ExternalSystemDataKeys.SELECTED_NODES.is(dataId)) return getSelectedNodes(ExternalSystemNode.class); - if (ExternalSystemDataKeys.PROJECTS_TREE.is(dataId)) return myTree; - if (ExternalSystemDataKeys.NOTIFICATION_GROUP.is(dataId)) return myNotificationGroup; + boolean getGroupTasks(); - return super.getData(dataId); - } - - @NotNull - public Project getProject() { - return myProject; - } - - @NotNull - public ExternalSystemUiAware getUiAware() { - return myUiAware; - } - - public ExternalSystemShortcutsManager getShortcutsManager() { - return myProjectsManager.getShortcutsManager(); - } - - public ExternalSystemTaskActivator getTaskActivator() { - return myProjectsManager.getTaskActivator(); - } - - @NotNull - public ProjectSystemId getSystemId() { - return myExternalSystemId; - } - - @NotNull - public NotificationGroup getNotificationGroup() { - return myNotificationGroup; - } - - public void init() { - initTree(); - - final ToolWindowManagerEx manager = ToolWindowManagerEx.getInstanceEx(myProject); - - final ToolWindowManagerAdapter listener = new ToolWindowManagerAdapter() { - boolean wasVisible = false; - - @Override - public void stateChanged() { - if (myToolWindow.isDisposed()) return; - boolean visible = myToolWindow.isVisible(); - if (!visible || wasVisible) { - wasVisible = visible; - return; - } - scheduleStructureUpdate(); - wasVisible = true; - } - }; - manager.addToolWindowManagerListener(listener); - - Disposer.register(myProject, new Disposable() { - public void dispose() { - manager.removeToolWindowManagerListener(listener); - } - }); - - getShortcutsManager().addListener(new ExternalSystemShortcutsManager.Listener() { - @Override - public void shortcutsUpdated() { - scheduleTasksUpdate(); - - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - myStructure.updateNodes(RunConfigurationNode.class); - } - }); - } - }); - - getTaskActivator().addListener(new ExternalSystemTaskActivator.Listener() { - @Override - public void tasksActivationChanged() { - scheduleTasksUpdate(); - - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - myStructure.updateNodes(RunConfigurationNode.class); - } - }); - } - }); - - ((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() { - private void changed() { - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - myStructure.visitNodes(ModuleNode.class, new Consumer() { - @Override - public void consume(ModuleNode node) { - node.updateRunConfigurations(); - } - }); - } - }); - } - - @Override - public void runConfigurationAdded(@NotNull RunnerAndConfigurationSettings settings) { - changed(); - } - - @Override - public void runConfigurationRemoved(@NotNull RunnerAndConfigurationSettings settings) { - changed(); - } - - @Override - public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) { - changed(); - } - }); - - ExternalSystemApiUtil.subscribe(myProject, myExternalSystemId, new ExternalSystemSettingsListenerAdapter(){ - @Override - public void onUseAutoImportChange(boolean currentValue, @NotNull final String linkedProjectPath) { - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - final List projectNodes = myStructure.getNodes(ProjectNode.class); - for (ProjectNode projectNode : projectNodes) { - final ProjectData projectData = projectNode.getData(); - if(projectData != null && projectData.getLinkedExternalProjectPath().equals(linkedProjectPath)) { - projectNode.updateProject(); - break; - } - } - } - }); - } - }); - - myToolWindow.setAdditionalGearActions(createAdditionalGearActionsGroup()); - - scheduleStructureUpdate(); - } - - private ActionGroup createAdditionalGearActionsGroup() { - ActionManager actionManager = ActionManager.getInstance(); - DefaultActionGroup group = new DefaultActionGroup(); - String[] ids = new String[]{"ExternalSystem.GroupTasks", "ExternalSystem.ShowInheritedTasks"}; - for (String id : ids) { - final AnAction gearAction = actionManager.getAction(id); - if (gearAction instanceof ExternalSystemViewGearAction) { - ((ExternalSystemViewGearAction)gearAction).setView(this); - group.add(gearAction); - } - } - return group; - } - - private void initStructure() { - myStructure = new ExternalProjectsStructure(myProject, this, myTree); - } - - private void initTree() { - myTree = new SimpleTree(); - myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); - - final ActionManager actionManager = ActionManager.getInstance(); - ActionToolbar actionToolbar = actionManager.createActionToolbar(myExternalSystemId.getReadableName() + " View Toolbar", - (DefaultActionGroup)actionManager - .getAction("ExternalSystemView.ActionsToolbar"), true); - - actionToolbar.setTargetComponent(myTree); - setToolbar(actionToolbar.getComponent()); - setContent(ScrollPaneFactory.createScrollPane(myTree)); - - myTree.addMouseListener(new PopupHandler() { - public void invokePopup(final Component comp, final int x, final int y) { - final String id = getMenuId(getSelectedNodes(ExternalSystemNode.class)); - if (id != null) { - final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(id); - if (actionGroup != null) { - actionManager.createActionPopupMenu("", actionGroup).getComponent().show(comp, x, y); - } - } - } - - @Nullable - private String getMenuId(Collection nodes) { - String id = null; - for (ExternalSystemNode node : nodes) { - String menuId = node.getMenuId(); - if (menuId == null) { - return null; - } - if (id == null) { - id = menuId; - } - else if (!id.equals(menuId)) { - return null; - } - } - return id; - } - }); - } - - public void scheduleStructureUpdate() { - scheduleStructureRequest(new Runnable() { - public void run() { - final Collection projectsData = - ProjectDataManager.getInstance().getExternalProjectsData(myProject, myExternalSystemId); - - final List> toImport = - ContainerUtil.mapNotNull(projectsData, new Function>() { - @Override - public DataNode fun(ExternalProjectInfo info) { - return info.getExternalProjectStructure(); - } - }); - - assert myStructure != null; - myStructure.updateProjects(toImport); - } - }); - } - - protected boolean isUnitTestMode() { - return ApplicationManager.getApplication().isUnitTestMode(); - } - - public static void invokeLater(Project p, Runnable r) { - invokeLater(p, ModalityState.defaultModalityState(), r); - } - - public static void invokeLater(final Project p, final ModalityState state, final Runnable r) { - if (isNoBackgroundMode()) { - r.run(); - } - else { - ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state); - } - } - - public static boolean isNoBackgroundMode() { - return (ApplicationManager.getApplication().isUnitTestMode() - || ApplicationManager.getApplication().isHeadlessEnvironment()); - } - - public void updateUpTo(ExternalSystemNode node) { - if (myStructure != null) { - myStructure.updateUpTo(node); - } - } - - @Nullable - protected ExternalProjectsStructure getStructure() { - return myStructure; - } - - @NotNull - public List> createNodes(@Nullable ExternalSystemNode parent, @NotNull DataNode dataNode) { - final List> result = new SmartList>(); - final Map, List>> groups = ExternalSystemApiUtil.group(dataNode.getChildren()); - for (ExternalSystemViewContributor contributor : ExternalSystemViewContributor.EP_NAME.getExtensions()) { - List> keys = contributor.getKeys(); - - final MultiMap, DataNode> dataNodes = MultiMap.create(); - for (Key key : keys) { - final List> values = groups.get(key); - if(key != null && values != null) { - dataNodes.put(key, values); - } - } - - if (dataNodes.isEmpty()) continue; - - final List> childNodes = contributor.createNodes(this, dataNodes); - result.addAll(childNodes); - - if (parent == null) continue; - - for (ExternalSystemNode childNode : childNodes) { - childNode.setParent(parent); - } - } - - return result; - } - - @Nullable - public ExternalProjectsViewState getState() { - ApplicationManager.getApplication().assertIsDispatchThread(); - if (myStructure != null) { - try { - myState.treeState = new Element("root"); - TreeState.createOn(myTree).writeExternal(myState.treeState); - } - catch (WriteExternalException e) { - LOG.warn(e); - } - } - return myState; - } - - public void loadState(ExternalProjectsViewState state) { - myState = state; - } - - public boolean getGroupTasks() { - return myState.groupTasks; - } - - public void setGroupTasks(boolean value) { - if (myState.groupTasks != value) { - myState.groupTasks = value; - scheduleTasksRebuild(); - } - } - - public boolean showInheritedTasks() { - return myState.showInheritedTasks; - } - - public void setShowInheritedTasks(boolean value) { - if (myState.showInheritedTasks != value) { - myState.showInheritedTasks = value; - scheduleStructureUpdate(); - } - } - - private void scheduleTasksRebuild() { - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - final List tasksNodes = myStructure.getNodes(TasksNode.class); - for (TasksNode tasksNode : tasksNodes) { - tasksNode.cleanUpCache(); - updateUpTo(tasksNode); - } - } - }); - } - - private void scheduleTasksUpdate() { - scheduleStructureRequest(new Runnable() { - public void run() { - assert myStructure != null; - myStructure.updateNodes(TaskNode.class); - } - }); - } - - private void scheduleStructureRequest(final Runnable r) { - if (isUnitTestMode()) { - r.run(); - return; - } - - invokeLater(myProject, new Runnable() { - public void run() { - if (!myToolWindow.isVisible()) return; - - boolean shouldCreate = myStructure == null; - if (shouldCreate) { - initStructure(); - } - - myTree.setPaintBusy(true); - try { - r.run(); - if (shouldCreate) { - restoreTreeState(); - } - } - finally { - myTree.setPaintBusy(false); - } - } - }); - } - - private void restoreTreeState() { - if (myState.treeState != null) { - TreeState treeState = new TreeState(); - try { - treeState.readExternal(myState.treeState); - treeState.applyTo(myTree); - } - catch (InvalidDataException e) { - LOG.info(e); - } - } - } - - private List getSelectedNodes(Class aClass) { - return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.emptyList(); - } - - private List getSelectedProjectNodes() { - return getSelectedNodes(ProjectNode.class); - } - - @Nullable - private ProjectNode getSelectedProjectNode() { - final List projectNodes = getSelectedProjectNodes(); - return projectNodes.size() == 1 ? projectNodes.get(0) : null; - } - - @Nullable - private Location extractLocation() { - final List selectedNodes = getSelectedNodes(ExternalSystemNode.class); - if (selectedNodes.isEmpty()) return null; - - List tasks = ContainerUtil.newSmartList(); - - ExternalTaskExecutionInfo taskExecutionInfo = new ExternalTaskExecutionInfo(); - - String projectPath = null; - - for (ExternalSystemNode node : selectedNodes) { - final Object data = node.getData(); - if (data instanceof TaskData) { - final TaskData taskData = (TaskData)data; - if (projectPath == null) { - projectPath = taskData.getLinkedExternalProjectPath(); - } - else if (!taskData.getLinkedExternalProjectPath().equals(projectPath)) { - return null; - } - - taskExecutionInfo.getSettings().getTaskNames().add(taskData.getName()); - taskExecutionInfo.getSettings().getTaskDescriptions().add(taskData.getDescription()); - tasks.add(taskData); - } - } - - if(tasks.isEmpty()) return null; - - taskExecutionInfo.getSettings().setExternalSystemIdString(myExternalSystemId.toString()); - taskExecutionInfo.getSettings().setExternalProjectPath(projectPath); - - String name = myExternalSystemId.getReadableName() + projectPath + StringUtil.join(taskExecutionInfo.getSettings().getTaskNames(), " "); - // We create a dummy text file instead of re-using external system file in order to avoid clashing with other configuration producers. - // For example gradle files are enhanced groovy scripts but we don't want to run them via regular IJ groovy script runners. - // Gradle tooling api should be used for running gradle tasks instead. IJ execution sub-system operates on Location objects - // which encapsulate PsiElement and groovy runners are automatically applied if that PsiElement IS-A GroovyFile. - PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(name, PlainTextFileType.INSTANCE, ""); - return new ExternalSystemTaskLocation(myProject, file, taskExecutionInfo); - } - - private VirtualFile extractVirtualFile() { - for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { - VirtualFile file = each.getVirtualFile(); - if (file != null && file.isValid()) return file; - } - - final ProjectNode projectNode = getSelectedProjectNode(); - if (projectNode == null) return null; - VirtualFile file = projectNode.getVirtualFile(); - if (file == null || !file.isValid()) return null; - return file; - } - - private Object extractVirtualFiles() { - final List files = new ArrayList(); - for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { - VirtualFile file = each.getVirtualFile(); - if (file != null && file.isValid()) files.add(file); - } - return files.isEmpty() ? null : VfsUtilCore.toVirtualFileArray(files); - } - - private Object extractNavigatables() { - final List navigatables = new ArrayList(); - for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { - Navigatable navigatable = each.getNavigatable(); - if (navigatable != null) navigatables.add(navigatable); - } - return navigatables.isEmpty() ? null : navigatables.toArray(new Navigatable[navigatables.size()]); - } + ProjectSystemId getSystemId(); } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewAdapter.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewAdapter.java new file mode 100644 index 000000000000..207ec6bbf6e6 --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewAdapter.java @@ -0,0 +1,93 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.externalSystem.view; + +import com.intellij.openapi.externalSystem.ExternalSystemUiAware; +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Vladislav.Soroka + * @since 4/15/2015 + */ +public class ExternalProjectsViewAdapter implements ExternalProjectsView { + @NotNull + private final ExternalProjectsView delegate; + + public ExternalProjectsViewAdapter(@NotNull ExternalProjectsView delegate) { + this.delegate = delegate; + } + + @Override + public ExternalSystemUiAware getUiAware() { + return delegate.getUiAware(); + } + + @Override + @Nullable + public ExternalProjectsStructure getStructure() { + return delegate.getStructure(); + } + + @Override + public ExternalSystemShortcutsManager getShortcutsManager() { + return delegate.getShortcutsManager(); + } + + @Override + public ExternalSystemTaskActivator getTaskActivator() { + return delegate.getTaskActivator(); + } + + @Override + public void updateUpTo(ExternalSystemNode node) { + delegate.updateUpTo(node); + } + + @Override + public List> createNodes(@NotNull ExternalProjectsView externalProjectsView, + @Nullable ExternalSystemNode parent, + @NotNull DataNode dataNode) { + return delegate.createNodes(externalProjectsView, parent, dataNode); + } + + @Override + public Project getProject() { + return delegate.getProject(); + } + + @Override + public boolean showInheritedTasks() { + return delegate.showInheritedTasks(); + } + + @Override + public boolean getGroupTasks() { + return delegate.getGroupTasks(); + } + + @Override + public ProjectSystemId getSystemId() { + return delegate.getSystemId(); + } +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java new file mode 100644 index 000000000000..b1ad9adf29d1 --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsViewImpl.java @@ -0,0 +1,620 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.externalSystem.view; + +import com.intellij.execution.*; +import com.intellij.ide.util.treeView.TreeState; +import com.intellij.notification.NotificationGroup; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.externalSystem.ExternalSystemUiAware; +import com.intellij.openapi.externalSystem.action.ExternalSystemViewGearAction; +import com.intellij.openapi.externalSystem.model.*; +import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo; +import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.model.task.TaskData; +import com.intellij.openapi.externalSystem.service.execution.ExternalSystemTaskLocation; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemShortcutsManager; +import com.intellij.openapi.externalSystem.service.project.manage.ExternalSystemTaskActivator; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; +import com.intellij.openapi.fileTypes.PlainTextFileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.SimpleToolWindowPanel; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; +import com.intellij.openapi.wm.impl.ToolWindowImpl; +import com.intellij.pom.Navigatable; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import com.intellij.ui.PopupHandler; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.treeStructure.SimpleTree; +import com.intellij.util.Consumer; +import com.intellij.util.DisposeAwareRunnable; +import com.intellij.util.Function; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; +import org.jdom.Element; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.TreeSelectionModel; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Vladislav.Soroka + * @since 9/19/2014 + */ +public class ExternalProjectsViewImpl extends SimpleToolWindowPanel implements DataProvider, ExternalProjectsView { + public static final Logger LOG = Logger.getInstance(ExternalProjectsViewImpl.class); + + @NotNull + private final Project myProject; + @NotNull + private final ExternalProjectsManager myProjectsManager; + @NotNull + private final ToolWindowEx myToolWindow; + @NotNull + private final ProjectSystemId myExternalSystemId; + @NotNull + private final ExternalSystemUiAware myUiAware; + + @Nullable + private ExternalProjectsStructure myStructure; + private SimpleTree myTree; + @NotNull + private final NotificationGroup myNotificationGroup; + + private ExternalProjectsViewState myState = new ExternalProjectsViewState(); + + public ExternalProjectsViewImpl(@NotNull Project project, @NotNull ToolWindowEx toolWindow, @NotNull ProjectSystemId externalSystemId) { + super(true, true); + myProject = project; + myToolWindow = toolWindow; + myExternalSystemId = externalSystemId; + myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); + myProjectsManager = ExternalProjectsManager.getInstance(myProject); + + String toolWindowId = + toolWindow instanceof ToolWindowImpl ? ((ToolWindowImpl)toolWindow).getId() : myExternalSystemId.getReadableName(); + + String notificationId = "notification.group.id." + externalSystemId.getId().toLowerCase(Locale.ENGLISH); + NotificationGroup registeredGroup = NotificationGroup.findRegisteredGroup(notificationId); + myNotificationGroup = registeredGroup != null ? registeredGroup : NotificationGroup.toolWindowGroup(notificationId, toolWindowId); + } + + @Nullable + @Override + public Object getData(@NonNls String dataId) { + if (ExternalSystemDataKeys.VIEW.is(dataId)) return this; + + if (PlatformDataKeys.HELP_ID.is(dataId)) return "reference.toolwindows.gradle"; + if (CommonDataKeys.PROJECT.is(dataId)) return myProject; + if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) return extractVirtualFile(); + if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return extractVirtualFiles(); + if (Location.DATA_KEY.is(dataId)) { + return extractLocation(); + } + if (CommonDataKeys.NAVIGATABLE_ARRAY.is(dataId)) return extractNavigatables(); + + if (ExternalSystemDataKeys.EXTERNAL_SYSTEM_ID.is(dataId)) return myExternalSystemId; + if (ExternalSystemDataKeys.UI_AWARE.is(dataId)) return myUiAware; + if (ExternalSystemDataKeys.SELECTED_PROJECT_NODE.is(dataId)) return getSelectedProjectNode(); + if (ExternalSystemDataKeys.SELECTED_NODES.is(dataId)) return getSelectedNodes(ExternalSystemNode.class); + if (ExternalSystemDataKeys.PROJECTS_TREE.is(dataId)) return myTree; + if (ExternalSystemDataKeys.NOTIFICATION_GROUP.is(dataId)) return myNotificationGroup; + + return super.getData(dataId); + } + + @NotNull + public Project getProject() { + return myProject; + } + + @NotNull + public ExternalSystemUiAware getUiAware() { + return myUiAware; + } + + public ExternalSystemShortcutsManager getShortcutsManager() { + return myProjectsManager.getShortcutsManager(); + } + + public ExternalSystemTaskActivator getTaskActivator() { + return myProjectsManager.getTaskActivator(); + } + + @NotNull + public ProjectSystemId getSystemId() { + return myExternalSystemId; + } + + @NotNull + public NotificationGroup getNotificationGroup() { + return myNotificationGroup; + } + + public void init() { + initTree(); + + final ToolWindowManagerEx manager = ToolWindowManagerEx.getInstanceEx(myProject); + + final ToolWindowManagerAdapter listener = new ToolWindowManagerAdapter() { + boolean wasVisible = false; + + @Override + public void stateChanged() { + if (myToolWindow.isDisposed()) return; + boolean visible = myToolWindow.isVisible(); + if (!visible || wasVisible) { + wasVisible = visible; + return; + } + scheduleStructureUpdate(); + wasVisible = true; + } + }; + manager.addToolWindowManagerListener(listener); + + Disposer.register(myProject, new Disposable() { + public void dispose() { + manager.removeToolWindowManagerListener(listener); + } + }); + + getShortcutsManager().addListener(new ExternalSystemShortcutsManager.Listener() { + @Override + public void shortcutsUpdated() { + scheduleTasksUpdate(); + + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + myStructure.updateNodes(RunConfigurationNode.class); + } + }); + } + }); + + getTaskActivator().addListener(new ExternalSystemTaskActivator.Listener() { + @Override + public void tasksActivationChanged() { + scheduleTasksUpdate(); + + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + myStructure.updateNodes(RunConfigurationNode.class); + } + }); + } + }); + + ((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() { + private void changed() { + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + myStructure.visitNodes(ModuleNode.class, new Consumer() { + @Override + public void consume(ModuleNode node) { + node.updateRunConfigurations(); + } + }); + } + }); + } + + @Override + public void runConfigurationAdded(@NotNull RunnerAndConfigurationSettings settings) { + changed(); + } + + @Override + public void runConfigurationRemoved(@NotNull RunnerAndConfigurationSettings settings) { + changed(); + } + + @Override + public void runConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) { + changed(); + } + }); + + ExternalSystemApiUtil.subscribe(myProject, myExternalSystemId, new ExternalSystemSettingsListenerAdapter(){ + @Override + public void onUseAutoImportChange(boolean currentValue, @NotNull final String linkedProjectPath) { + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + final List projectNodes = myStructure.getNodes(ProjectNode.class); + for (ProjectNode projectNode : projectNodes) { + final ProjectData projectData = projectNode.getData(); + if(projectData != null && projectData.getLinkedExternalProjectPath().equals(linkedProjectPath)) { + projectNode.updateProject(); + break; + } + } + } + }); + } + }); + + myToolWindow.setAdditionalGearActions(createAdditionalGearActionsGroup()); + + scheduleStructureUpdate(); + } + + private ActionGroup createAdditionalGearActionsGroup() { + ActionManager actionManager = ActionManager.getInstance(); + DefaultActionGroup group = new DefaultActionGroup(); + String[] ids = new String[]{"ExternalSystem.GroupTasks", "ExternalSystem.ShowInheritedTasks"}; + for (String id : ids) { + final AnAction gearAction = actionManager.getAction(id); + if (gearAction instanceof ExternalSystemViewGearAction) { + ((ExternalSystemViewGearAction)gearAction).setView(this); + group.add(gearAction); + } + } + return group; + } + + private void initStructure() { + myStructure = new ExternalProjectsStructure(myProject, myTree); + myStructure.init(this); + } + + private void initTree() { + myTree = new SimpleTree(); + myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + + final ActionManager actionManager = ActionManager.getInstance(); + ActionToolbar actionToolbar = actionManager.createActionToolbar(myExternalSystemId.getReadableName() + " View Toolbar", + (DefaultActionGroup)actionManager + .getAction("ExternalSystemView.ActionsToolbar"), true); + + actionToolbar.setTargetComponent(myTree); + setToolbar(actionToolbar.getComponent()); + setContent(ScrollPaneFactory.createScrollPane(myTree)); + + myTree.addMouseListener(new PopupHandler() { + public void invokePopup(final Component comp, final int x, final int y) { + final String id = getMenuId(getSelectedNodes(ExternalSystemNode.class)); + if (id != null) { + final ActionGroup actionGroup = (ActionGroup)actionManager.getAction(id); + if (actionGroup != null) { + actionManager.createActionPopupMenu("", actionGroup).getComponent().show(comp, x, y); + } + } + } + + @Nullable + private String getMenuId(Collection nodes) { + String id = null; + for (ExternalSystemNode node : nodes) { + String menuId = node.getMenuId(); + if (menuId == null) { + return null; + } + if (id == null) { + id = menuId; + } + else if (!id.equals(menuId)) { + return null; + } + } + return id; + } + }); + } + + public void scheduleStructureUpdate() { + scheduleStructureRequest(new Runnable() { + public void run() { + final Collection projectsData = + ProjectDataManager.getInstance().getExternalProjectsData(myProject, myExternalSystemId); + + final List> toImport = + ContainerUtil.mapNotNull(projectsData, new Function>() { + @Override + public DataNode fun(ExternalProjectInfo info) { + return info.getExternalProjectStructure(); + } + }); + + assert myStructure != null; + myStructure.updateProjects(toImport); + } + }); + } + + protected boolean isUnitTestMode() { + return ApplicationManager.getApplication().isUnitTestMode(); + } + + public static void invokeLater(Project p, Runnable r) { + invokeLater(p, ModalityState.defaultModalityState(), r); + } + + public static void invokeLater(final Project p, final ModalityState state, final Runnable r) { + if (isNoBackgroundMode()) { + r.run(); + } + else { + ApplicationManager.getApplication().invokeLater(DisposeAwareRunnable.create(r, p), state); + } + } + + public static boolean isNoBackgroundMode() { + return (ApplicationManager.getApplication().isUnitTestMode() + || ApplicationManager.getApplication().isHeadlessEnvironment()); + } + + public void updateUpTo(ExternalSystemNode node) { + ExternalProjectsStructure structure = getStructure(); + if (structure != null) { + structure.updateUpTo(node); + } + } + + @Nullable + public ExternalProjectsStructure getStructure() { + return myStructure; + } + + @NotNull + public List> createNodes(@NotNull ExternalProjectsView externalProjectsView, + @Nullable ExternalSystemNode parent, + @NotNull DataNode dataNode) { + final List> result = new SmartList>(); + final Map, List>> groups = ExternalSystemApiUtil.group(dataNode.getChildren()); + for (ExternalSystemViewContributor contributor : ExternalSystemViewContributor.EP_NAME.getExtensions()) { + List> keys = contributor.getKeys(); + + final MultiMap, DataNode> dataNodes = MultiMap.create(); + for (Key key : keys) { + final List> values = groups.get(key); + if(key != null && values != null) { + dataNodes.put(key, values); + } + } + + if (dataNodes.isEmpty()) continue; + + final List> childNodes = contributor.createNodes(externalProjectsView, dataNodes); + result.addAll(childNodes); + + if (parent == null) continue; + + for (ExternalSystemNode childNode : childNodes) { + childNode.setParent(parent); + } + } + + return result; + } + + @Nullable + public ExternalProjectsViewState getState() { + ApplicationManager.getApplication().assertIsDispatchThread(); + if (myStructure != null) { + try { + myState.treeState = new Element("root"); + TreeState.createOn(myTree).writeExternal(myState.treeState); + } + catch (WriteExternalException e) { + LOG.warn(e); + } + } + return myState; + } + + public void loadState(ExternalProjectsViewState state) { + myState = state; + } + + public boolean getGroupTasks() { + return myState.groupTasks; + } + + public void setGroupTasks(boolean value) { + if (myState.groupTasks != value) { + myState.groupTasks = value; + scheduleTasksRebuild(); + } + } + + public boolean showInheritedTasks() { + return myState.showInheritedTasks; + } + + public void setShowInheritedTasks(boolean value) { + if (myState.showInheritedTasks != value) { + myState.showInheritedTasks = value; + scheduleStructureUpdate(); + } + } + + private void scheduleTasksRebuild() { + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + final List tasksNodes = myStructure.getNodes(TasksNode.class); + for (TasksNode tasksNode : tasksNodes) { + tasksNode.cleanUpCache(); + updateUpTo(tasksNode); + } + } + }); + } + + private void scheduleTasksUpdate() { + scheduleStructureRequest(new Runnable() { + public void run() { + assert myStructure != null; + myStructure.updateNodes(TaskNode.class); + } + }); + } + + private void scheduleStructureRequest(final Runnable r) { + if (isUnitTestMode()) { + r.run(); + return; + } + + invokeLater(myProject, new Runnable() { + public void run() { + if (!myToolWindow.isVisible()) return; + + boolean shouldCreate = myStructure == null; + if (shouldCreate) { + initStructure(); + } + + myTree.setPaintBusy(true); + try { + r.run(); + if (shouldCreate) { + restoreTreeState(); + } + } + finally { + myTree.setPaintBusy(false); + } + } + }); + } + + private void restoreTreeState() { + if (myState.treeState != null) { + TreeState treeState = new TreeState(); + try { + treeState.readExternal(myState.treeState); + treeState.applyTo(myTree); + } + catch (InvalidDataException e) { + LOG.info(e); + } + } + } + + private List getSelectedNodes(Class aClass) { + return myStructure != null ? myStructure.getSelectedNodes(myTree, aClass) : ContainerUtil.emptyList(); + } + + private List getSelectedProjectNodes() { + return getSelectedNodes(ProjectNode.class); + } + + @Nullable + private ProjectNode getSelectedProjectNode() { + final List projectNodes = getSelectedProjectNodes(); + return projectNodes.size() == 1 ? projectNodes.get(0) : null; + } + + @Nullable + private Location extractLocation() { + final List selectedNodes = getSelectedNodes(ExternalSystemNode.class); + if (selectedNodes.isEmpty()) return null; + + List tasks = ContainerUtil.newSmartList(); + + ExternalTaskExecutionInfo taskExecutionInfo = new ExternalTaskExecutionInfo(); + + String projectPath = null; + + for (ExternalSystemNode node : selectedNodes) { + final Object data = node.getData(); + if (data instanceof TaskData) { + final TaskData taskData = (TaskData)data; + if (projectPath == null) { + projectPath = taskData.getLinkedExternalProjectPath(); + } + else if (!taskData.getLinkedExternalProjectPath().equals(projectPath)) { + return null; + } + + taskExecutionInfo.getSettings().getTaskNames().add(taskData.getName()); + taskExecutionInfo.getSettings().getTaskDescriptions().add(taskData.getDescription()); + tasks.add(taskData); + } + } + + if(tasks.isEmpty()) return null; + + taskExecutionInfo.getSettings().setExternalSystemIdString(myExternalSystemId.toString()); + taskExecutionInfo.getSettings().setExternalProjectPath(projectPath); + + String name = myExternalSystemId.getReadableName() + projectPath + StringUtil.join(taskExecutionInfo.getSettings().getTaskNames(), " "); + // We create a dummy text file instead of re-using external system file in order to avoid clashing with other configuration producers. + // For example gradle files are enhanced groovy scripts but we don't want to run them via regular IJ groovy script runners. + // Gradle tooling api should be used for running gradle tasks instead. IJ execution sub-system operates on Location objects + // which encapsulate PsiElement and groovy runners are automatically applied if that PsiElement IS-A GroovyFile. + PsiFile file = PsiFileFactory.getInstance(myProject).createFileFromText(name, PlainTextFileType.INSTANCE, ""); + return new ExternalSystemTaskLocation(myProject, file, taskExecutionInfo); + } + + private VirtualFile extractVirtualFile() { + for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { + VirtualFile file = each.getVirtualFile(); + if (file != null && file.isValid()) return file; + } + + final ProjectNode projectNode = getSelectedProjectNode(); + if (projectNode == null) return null; + VirtualFile file = projectNode.getVirtualFile(); + if (file == null || !file.isValid()) return null; + return file; + } + + private Object extractVirtualFiles() { + final List files = new ArrayList(); + for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { + VirtualFile file = each.getVirtualFile(); + if (file != null && file.isValid()) files.add(file); + } + return files.isEmpty() ? null : VfsUtilCore.toVirtualFileArray(files); + } + + private Object extractNavigatables() { + final List navigatables = new ArrayList(); + for (ExternalSystemNode each : getSelectedNodes(ExternalSystemNode.class)) { + Navigatable navigatable = each.getNavigatable(); + if (navigatable != null) navigatables.add(navigatable); + } + return navigatables.isEmpty() ? null : navigatables.toArray(new Navigatable[navigatables.size()]); + } +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalSystemNode.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalSystemNode.java index dbe5e0d3154c..33da6647dda0 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalSystemNode.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalSystemNode.java @@ -157,7 +157,12 @@ public abstract class ExternalSystemNode extends SimpleNode implements Compar } public ExternalProjectsStructure.DisplayKind getDisplayKind() { - return ExternalProjectsStructure.DisplayKind.NORMAL; + Class[] visibles = getStructure().getVisibleNodesClasses(); + if (visibles == null) return ExternalProjectsStructure.DisplayKind.NORMAL; + for (Class each : visibles) { + if (each.isInstance(this)) return ExternalProjectsStructure.DisplayKind.ALWAYS; + } + return ExternalProjectsStructure.DisplayKind.NEVER; } @NotNull @@ -270,7 +275,8 @@ public abstract class ExternalSystemNode extends SimpleNode implements Compar @NotNull protected List doBuildChildren() { if (myDataNode != null && !myDataNode.getChildren().isEmpty()) { - return getExternalProjectsView().createNodes(this, myDataNode); + final ExternalProjectsView externalProjectsView = getExternalProjectsView(); + return externalProjectsView.createNodes(externalProjectsView, this, myDataNode); } else { return myChildrenList; diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ModuleNode.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ModuleNode.java index 31e88e962910..b70a68d7854a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ModuleNode.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ModuleNode.java @@ -81,7 +81,7 @@ public class ModuleNode extends ExternalSystemNode { @Override public boolean isVisible() { - return true; + return super.isVisible(); } @Override diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/RunConfigurationsNode.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/RunConfigurationsNode.java index ca826684c3d9..9e316880c3fd 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/RunConfigurationsNode.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/RunConfigurationsNode.java @@ -60,7 +60,7 @@ public class RunConfigurationsNode extends ExternalSystemNode { @Override public boolean isVisible() { - return hasChildren() && super.isVisible(); + return super.isVisible() && hasChildren(); } @NotNull diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/TasksNode.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/TasksNode.java index 7b15ef59769a..941bc9a0a359 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/TasksNode.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/TasksNode.java @@ -68,7 +68,7 @@ public class TasksNode extends ExternalSystemNode { @Override public boolean isVisible() { - return hasChildren() && super.isVisible(); + return super.isVisible() && hasChildren(); } @SuppressWarnings("unchecked") @@ -95,7 +95,7 @@ public class TasksNode extends ExternalSystemNode { @Override public boolean isVisible() { - return hasChildren() && super.isVisible(); + return super.isVisible() && hasChildren(); } @Override diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft index 170d1acfc457..28e79a383f86 100644 --- a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft +++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft @@ -1,7 +1,13 @@ apply plugin: 'java' sourceCompatibility = 1.5 -version = '1.0' + +#if (${MODULE_GROUP} && ${MODULE_GROUP} != "") +group '${MODULE_GROUP}' +#end +#if (${MODULE_VERSION} && ${MODULE_VERSION} != "") +version '${MODULE_VERSION}' +#end task wrapper(type: Wrapper) { gradleVersion = '1.9' diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script.gradle.ft index 072e5e57717b..f0e6de802fdc 100644 --- a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script.gradle.ft +++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script.gradle.ft @@ -1,7 +1,13 @@ apply plugin: 'java' sourceCompatibility = 1.5 -version = '1.0' + +#if (${MODULE_GROUP} && ${MODULE_GROUP} != "") +group '${MODULE_GROUP}' +#end +#if (${MODULE_VERSION} && ${MODULE_VERSION} != "") +version '${MODULE_VERSION}' +#end repositories { mavenCentral() diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft index 73f1b4e61a05..36dca663ec7a 100644 --- a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft +++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft @@ -1,6 +1,12 @@ -#if (${CONTENT} && ${CONTENT} != "")${CONTENT}#end -#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "")include '${MODULE_DIR_NAME}' -#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}' +#if (${CONTENT} && ${CONTENT} != "")${CONTENT} +#end +#if (${MODULE_PATH} && ${MODULE_PATH} != "") +#if (${MODULE_FLAT_DIR} == "true")includeFlat '${MODULE_PATH}' +#else +include '${MODULE_PATH}' +#end +#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_PATH} != ${MODULE_NAME}) +findProject(':${MODULE_PATH}')?.name = '${MODULE_NAME}' #end #end diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft index 9fbc0dee9bbd..0dc6b90a6532 100644 --- a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft +++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft @@ -1,11 +1,17 @@ #if (${PROJECT_NAME} && ${PROJECT_NAME} != "") -#if (((!${MODULE_DIR_NAME} || ${MODULE_DIR_NAME} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != ""))rootProject.name = '${MODULE_NAME}' -#elseif(true)rootProject.name = '${PROJECT_NAME}' +#if (((!${MODULE_PATH} || ${MODULE_PATH} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != "")) +rootProject.name = '${MODULE_NAME}' +#else +rootProject.name = '${PROJECT_NAME}' #end #end -#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "") -include '${MODULE_DIR_NAME}' -#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}' +#if (${MODULE_PATH} && ${MODULE_PATH} != "") +#if (${MODULE_FLAT_DIR} == "true")includeFlat '${MODULE_PATH}' +#else +include '${MODULE_PATH}' +#end +#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_PATH} != ${MODULE_NAME}) +findProject(':${MODULE_PATH}')?.name = '${MODULE_NAME}' #end #end diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/UseDistributionWithSourcesNotificationProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/UseDistributionWithSourcesNotificationProvider.java index 7b06640f6234..ce5d35bc6c24 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/UseDistributionWithSourcesNotificationProvider.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInsight/UseDistributionWithSourcesNotificationProvider.java @@ -16,17 +16,10 @@ package org.jetbrains.plugins.gradle.codeInsight; import com.intellij.ProjectTopics; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.externalSystem.model.DataNode; -import com.intellij.openapi.externalSystem.model.project.ProjectData; -import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback; -import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; -import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; -import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; @@ -35,7 +28,6 @@ import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModuleRootAdapter; import com.intellij.openapi.roots.ModuleRootEvent; -import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -120,32 +112,9 @@ public class UseDistributionWithSourcesNotificationProvider extends EditorNotifi public void run() { updateDefaultWrapperConfiguration(rootProjectPath); EditorNotifications.getInstance(module.getProject()).updateAllNotifications(); - final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class); ExternalSystemUtil.refreshProject( - module.getProject(), GradleConstants.SYSTEM_ID, settings.getExternalProjectPath(), - new ExternalProjectRefreshCallback() { - @Override - public void onSuccess(@Nullable final DataNode externalProject) { - if (externalProject == null) { - return; - } - ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(module.getProject()) { - @Override - public void execute() { - ProjectRootManagerEx.getInstanceEx(module.getProject()).mergeRootsChangesDuring(new Runnable() { - @Override - public void run() { - projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), module.getProject(), true); - } - }); - } - }); - } - - @Override - public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) { - } - }, true, ProgressExecutionMode.START_IN_FOREGROUND_ASYNC); + module.getProject(), GradleConstants.SYSTEM_ID, settings.getExternalProjectPath(), true, + ProgressExecutionMode.START_IN_FOREGROUND_ASYNC); } }); return panel; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index 154036d043c8..54fc2559316c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -32,6 +32,8 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemDebugEnvironment; import com.intellij.openapi.util.KeyValue; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.StreamUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.BooleanFunction; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -255,6 +257,10 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver moduleDataNode = projectDataNode.createChild(ProjectKeys.MODULE, moduleData); moduleMap.put(moduleName, Pair.create(moduleDataNode, gradleModule)); + if(StringUtil.equals(moduleData.getLinkedExternalProjectPath(), projectData.getLinkedExternalProjectPath())) { + projectData.setGroup(moduleData.getGroup()); + projectData.setVersion(moduleData.getVersion()); + } } // populate modules nodes diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java index 3dd4682b59ff..b9cbeb2e0b66 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java @@ -17,25 +17,34 @@ package org.jetbrains.plugins.gradle.service.project.wizard; import com.intellij.ide.fileTemplates.FileTemplate; import com.intellij.ide.fileTemplates.FileTemplateManager; +import com.intellij.ide.projectWizard.ProjectSettingsStep; +import com.intellij.ide.util.EditorHelper; import com.intellij.ide.util.projectWizard.JavaModuleBuilder; import com.intellij.ide.util.projectWizard.ModuleWizardStep; +import com.intellij.ide.util.projectWizard.SettingsStep; import com.intellij.ide.util.projectWizard.WizardContext; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; +import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.model.project.ProjectId; +import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode; import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder; import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; -import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.module.*; +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.module.JavaModuleType; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.projectRoots.JavaSdkType; import com.intellij.openapi.projectRoots.SdkTypeId; -import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.util.io.FileUtil; @@ -45,6 +54,9 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,10 +84,19 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder( + wizardContext, this, new GradleProjectSettingsControl(getExternalProjectSettings())) + }; } @Nullable @Override public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) { - if (!myWizardContext.isCreatingNewProject()) return new ModuleWizardStep() { + return new ModuleWizardStep() { @Override public JComponent getComponent() { return new JPanel(); @@ -139,11 +198,8 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder(this, settingsControl); } @Override @@ -167,69 +223,61 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder attributes = ContainerUtil.newHashMap(); + if (myProjectId != null) { + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_VERSION, myProjectId.getVersion()); + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_GROUP, myProjectId.getGroupId()); + } saveFile(file, templateName, attributes); } return file; } @Nullable - private VirtualFile setupGradleSettingsFile(@NotNull VirtualFile modelContentRootDir, @NotNull ModifiableRootModel model) + private VirtualFile setupGradleSettingsFile(@NotNull String rootProjectPath, + @NotNull VirtualFile modelContentRootDir, + @NotNull ModifiableRootModel model) throws ConfigurationException { - VirtualFile file = null; - if (myWizardContext.isCreatingNewProject()) { - final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, model.getProject().getBaseDir(), '/'); - file = getExternalProjectConfigFile(model.getProject().getBasePath(), GradleConstants.SETTINGS_FILE_NAME); - if (file == null) return null; + final VirtualFile file = getOrCreateExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME); + if (file == null) return null; + + final String moduleName = myProjectId == null ? model.getModule().getName() : myProjectId.getArtifactId(); + if (myWizardContext.isCreatingNewProject() || myParentProject == null) { + final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, file.getParent(), '/'); Map attributes = ContainerUtil.newHashMap(); final String projectName = model.getProject().getName(); attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName); - attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName); - attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName()); + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, moduleDirName); + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName); saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes); } else { - Map moduleMap = ContainerUtil.newHashMap(); - for (Module module : ModuleManager.getInstance(model.getProject()).getModules()) { - for (ContentEntry contentEntry : model.getContentEntries()) { - if (contentEntry.getFile() != null) { - moduleMap.put(contentEntry.getFile().getPath(), module); - } - } + char separatorChar = file.getParent() == null || !VfsUtilCore.isAncestor(file.getParent(), modelContentRootDir, true) ? '/' : ':'; + String modulePath = VfsUtil.getPath(file, modelContentRootDir, separatorChar); + + Map attributes = ContainerUtil.newHashMap(); + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, moduleName); + // check for flat structure + final String flatStuctureModulePath = + modulePath != null && StringUtil.startsWith(modulePath, "../") ? StringUtil.trimStart(modulePath, "../") : null; + if (StringUtil.equals(flatStuctureModulePath, modelContentRootDir.getName())) { + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_FLAT_DIR, "true"); + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, flatStuctureModulePath); + } + else { + attributes.put(TEMPLATE_ATTRIBUTE_MODULE_PATH, modulePath); } - VirtualFile virtualFile = modelContentRootDir; - Module module = null; - while (virtualFile != null && module == null) { - module = moduleMap.get(virtualFile.getPath()); - virtualFile = virtualFile.getParent(); - } - - if (module != null) { - String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY); - - if (!StringUtil.isEmpty(rootProjectPath)) { - VirtualFile rootProjectFile = VfsUtil.findFileByIoFile(new File(rootProjectPath), true); - if (rootProjectFile == null) return null; - - final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, rootProjectFile, '/'); - file = getExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME); - if (file == null) return null; - - Map attributes = ContainerUtil.newHashMap(); - attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName); - attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName()); - appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes); - } - } + appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes); } return file; } @@ -239,7 +287,9 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleWizardStep.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleWizardStep.java new file mode 100644 index 000000000000..e8a5a78f72dd --- /dev/null +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleWizardStep.java @@ -0,0 +1,282 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.gradle.service.project.wizard; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.ide.util.projectWizard.ModuleWizardStep; +import com.intellij.ide.util.projectWizard.WizardContext; +import com.intellij.openapi.externalSystem.model.ExternalProjectInfo; +import com.intellij.openapi.externalSystem.model.project.ProjectData; +import com.intellij.openapi.externalSystem.model.project.ProjectId; +import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; +import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.util.GradleConstants; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * @author Vladislav.Soroka + * @since 4/15/2015 + */ +public class GradleModuleWizardStep extends ModuleWizardStep { + private static final Icon WIZARD_ICON = null; + + private static final String INHERIT_GROUP_ID_KEY = "GradleModuleWizard.inheritGroupId"; + private static final String INHERIT_VERSION_KEY = "GradleModuleWizard.inheritVersion"; + + @Nullable + private final Project myProjectOrNull; + @NotNull + private final GradleModuleBuilder myBuilder; + @NotNull + private final WizardContext myContext; + @Nullable + private ProjectData myParent; + + private String myInheritedGroupId; + private String myInheritedVersion; + + private JPanel myMainPanel; + + private JLabel myParentNameLabel; + private JButton mySelectParent; + + private JTextField myGroupIdField; + private JCheckBox myInheritGroupIdCheckBox; + private JTextField myArtifactIdField; + private JTextField myVersionField; + private JCheckBox myInheritVersionCheckBox; + + private JPanel myAddToPanel; + + + public GradleModuleWizardStep(@NotNull GradleModuleBuilder builder, @NotNull WizardContext context) { + myProjectOrNull = context.getProject(); + myBuilder = builder; + myContext = context; + initComponents(); + loadSettings(); + } + + private void initComponents() { + mySelectParent.setIcon(AllIcons.Actions.Module); + mySelectParent.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + myParent = doSelectProject(myParent); + updateComponents(); + } + }); + + ActionListener updatingListener = new ActionListener() { + public void actionPerformed(ActionEvent e) { + updateComponents(); + } + }; + myInheritGroupIdCheckBox.addActionListener(updatingListener); + myInheritVersionCheckBox.addActionListener(updatingListener); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myGroupIdField; + } + + private ProjectData doSelectProject(ProjectData current) { + assert myProjectOrNull != null : "must not be called when creating a new project"; + + SelectExternalProjectDialog d = new SelectExternalProjectDialog(myProjectOrNull, current); + if (!d.showAndGet()) { + return current; + } + return d.getResult(); + } + + @Override + public void onStepLeaving() { + saveSettings(); + } + + private void loadSettings() { + myBuilder.setInheritGroupId(getSavedValue(INHERIT_GROUP_ID_KEY, true)); + myBuilder.setInheritVersion(getSavedValue(INHERIT_VERSION_KEY, true)); + } + + private void saveSettings() { + saveValue(INHERIT_GROUP_ID_KEY, myInheritGroupIdCheckBox.isSelected()); + saveValue(INHERIT_VERSION_KEY, myInheritVersionCheckBox.isSelected()); + } + + private static boolean getSavedValue(String key, boolean defaultValue) { + return getSavedValue(key, String.valueOf(defaultValue)).equals(String.valueOf(true)); + } + + private static String getSavedValue(String key, String defaultValue) { + String value = PropertiesComponent.getInstance().getValue(key); + return value == null ? defaultValue : value; + } + + private static void saveValue(String key, boolean value) { + saveValue(key, String.valueOf(value)); + } + + private static void saveValue(String key, String value) { + PropertiesComponent props = PropertiesComponent.getInstance(); + props.setValue(key, value); + } + + public JComponent getComponent() { + return myMainPanel; + } + + @Override + public boolean validate() throws ConfigurationException { + if (StringUtil.isEmptyOrSpaces(myArtifactIdField.getText())) { + throw new ConfigurationException("Please, specify artifactId"); + } + + return true; + } + + @Nullable + public ProjectData findPotentialParentProject(@Nullable Project project) { + if (project == null) return null; + + final ExternalProjectInfo projectInfo = + ProjectDataManager.getInstance().getExternalProjectData(project, GradleConstants.SYSTEM_ID, myContext.getProjectFileDirectory()); + return projectInfo != null && projectInfo.getExternalProjectStructure() != null + ? projectInfo.getExternalProjectStructure().getData() + : null; + } + + private static void setTestIfEmpty(@NotNull JTextField artifactIdField, @Nullable String text) { + if (StringUtil.isEmpty(artifactIdField.getText())) { + artifactIdField.setText(StringUtil.notNullize(text)); + } + } + + @Override + public void updateStep() { + myParent = findPotentialParentProject(myProjectOrNull); + + ProjectId projectId = myBuilder.getProjectId(); + + if (projectId == null) { + setTestIfEmpty(myArtifactIdField, myBuilder.getName()); + setTestIfEmpty(myGroupIdField, myParent == null ? myBuilder.getName() : myParent.getGroup()); + setTestIfEmpty(myVersionField, myParent == null ? "1.0-SNAPSHOT" : myParent.getVersion()); + } + else { + setTestIfEmpty(myArtifactIdField, projectId.getArtifactId()); + setTestIfEmpty(myGroupIdField, projectId.getGroupId()); + setTestIfEmpty(myVersionField, projectId.getVersion()); + } + + myInheritGroupIdCheckBox.setSelected(myBuilder.isInheritGroupId()); + myInheritVersionCheckBox.setSelected(myBuilder.isInheritVersion()); + + updateComponents(); + } + + + private void updateComponents() { + boolean isAddToVisible = !myContext.isCreatingNewProject() && myProjectOrNull != null && isGradleModuleExist(); + + myAddToPanel.setVisible(isAddToVisible); + myInheritGroupIdCheckBox.setVisible(isAddToVisible); + myInheritVersionCheckBox.setVisible(isAddToVisible); + + myParentNameLabel.setText(formatProjectString(myParent)); + + if (myParent == null) { + myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.FALSE); + myGroupIdField.setEnabled(true); + myVersionField.setEnabled(true); + myInheritGroupIdCheckBox.setEnabled(false); + myInheritVersionCheckBox.setEnabled(false); + } + else { + myContext.putUserData(ExternalModuleSettingsStep.SKIP_STEP_KEY, Boolean.TRUE); + myGroupIdField.setEnabled(!myInheritGroupIdCheckBox.isSelected()); + myVersionField.setEnabled(!myInheritVersionCheckBox.isSelected()); + + if (myInheritGroupIdCheckBox.isSelected() + || myGroupIdField.getText().equals(myInheritedGroupId)) { + myGroupIdField.setText(myParent.getGroup()); + } + if (myInheritVersionCheckBox.isSelected() + || myVersionField.getText().equals(myInheritedVersion)) { + myVersionField.setText(myParent.getVersion()); + } + myInheritedGroupId = myGroupIdField.getText(); + myInheritedVersion = myVersionField.getText(); + + myInheritGroupIdCheckBox.setEnabled(true); + myInheritVersionCheckBox.setEnabled(true); + } + } + + private boolean isGradleModuleExist() { + for (Module module : myContext.getModulesProvider().getModules()) { + if (ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) return true; + } + return false; + } + + private static String formatProjectString(ProjectData moduleData) { + if (moduleData == null) return ""; + return moduleData.toString(); + } + + @Override + public void updateDataModel() { + myContext.setProjectBuilder(myBuilder); + myBuilder.setParentProject(myParent); + + myBuilder.setProjectId(new ProjectId(myGroupIdField.getText(), + myArtifactIdField.getText(), + myVersionField.getText())); + myBuilder.setInheritGroupId(myInheritGroupIdCheckBox.isSelected()); + myBuilder.setInheritVersion(myInheritVersionCheckBox.isSelected()); + + if (StringUtil.isNotEmpty(myBuilder.getProjectId().getArtifactId())) { + myContext.setProjectName(myBuilder.getProjectId().getArtifactId()); + } + if (myParent != null) { + myContext.setProjectFileDirectory(myParent.getLinkedExternalProjectPath() + '/' + myContext.getProjectName()); + } + else { + if (myProjectOrNull != null) { + myContext.setProjectFileDirectory(myProjectOrNull.getBaseDir().getPath() + '/' + myContext.getProjectName()); + } + } + } + + @Override + public Icon getIcon() { + return WIZARD_ICON; + } +} + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java index 10f766cc5e34..c4479ce860b0 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleProjectOpenProcessor.java @@ -52,7 +52,7 @@ public class GradleProjectOpenProcessor extends ProjectOpenProcessorBase nodeClass, + NodeSelector selector) { + super(project, false); + mySelector = selector; + setTitle(title); + + myTree = new SimpleTree(); + myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + + final ExternalProjectsView projectsView = ExternalProjectsManager.getInstance(project).getExternalProjectsView(GradleConstants.SYSTEM_ID); + if(projectsView != null) { + final ExternalProjectsStructure treeStructure = new ExternalProjectsStructure(project, myTree) { + @Override + protected Class[] getVisibleNodesClasses() { + return new Class[]{nodeClass}; + } + }; + treeStructure.init(new ExternalProjectsViewAdapter(projectsView) { + @Nullable + @Override + public ExternalProjectsStructure getStructure() { + return treeStructure; + } + + @Override + public void updateUpTo(ExternalSystemNode node) { + treeStructure.updateUpTo(node); + } + }); + + final Collection projectsData = + ProjectDataManager.getInstance().getExternalProjectsData(project, GradleConstants.SYSTEM_ID); + + final List> dataNodes = + ContainerUtil.mapNotNull(projectsData, new Function>() { + @Override + public DataNode fun(ExternalProjectInfo info) { + return info.getExternalProjectStructure(); + } + }); + treeStructure.updateProjects(dataNodes); + + final SimpleNode[] selection = new SimpleNode[]{null}; + treeStructure.accept(new SimpleNodeVisitor() { + public boolean accept(SimpleNode each) { + if (!mySelector.shouldSelect(each)) return false; + selection[0] = each; + return true; + } + }); + if (selection[0] != null) { + treeStructure.select(selection[0]); + } + } + + init(); + } + + protected SimpleNode getSelectedNode() { + return myTree.getNodeFor(myTree.getSelectionPath()); + } + + @Nullable + protected JComponent createCenterPanel() { + final JScrollPane pane = ScrollPaneFactory.createScrollPane(myTree); + pane.setPreferredSize(JBUI.size(320, 400)); + return pane; + } + + protected interface NodeSelector { + boolean shouldSelect(SimpleNode node); + } +}