diff --git a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java index 29f991c88712..9deea918441a 100644 --- a/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java +++ b/java/java-impl/src/com/intellij/externalSystem/JavaProjectData.java @@ -17,6 +17,7 @@ package com.intellij.externalSystem; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.externalSystem.model.Key; +import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; @@ -33,9 +34,9 @@ import java.util.regex.Pattern; * @since 4/12/13 12:27 PM */ public class JavaProjectData extends AbstractExternalEntityData { - - @NotNull public static final Key KEY = Key.create(JavaProjectData.class); - + + @NotNull public static final Key KEY = Key.create(JavaProjectData.class, ProjectKeys.PROJECT.getProcessingWeight() + 1); + private static final Logger LOG = Logger.getInstance("#" + JavaProjectData.class.getName()); private static final long serialVersionUID = 1L; @@ -47,7 +48,7 @@ public class JavaProjectData extends AbstractExternalEntityData { @NotNull private JavaSdkVersion myJdkVersion = DEFAULT_JDK_VERSION; @NotNull private LanguageLevel myLanguageLevel = DEFAULT_LANGUAGE_LEVEL; - @NotNull private String myCompileOutputPath; + @NotNull private String myCompileOutputPath; public JavaProjectData(@NotNull ProjectSystemId owner, @NotNull String compileOutputPath) { super(owner); diff --git a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties index b84076080db0..58e2981cdff9 100644 --- a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties +++ b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties @@ -31,8 +31,8 @@ tool.window.title.tasks=tasks # Action. action.refresh.all.projects.text=Refresh all {0} projects action.refresh.all.projects.description=Force refresh all linked {0} projects -action.task.run.text=Run -action.task.run.description=Run selected task +action.detach.external.project.text=Detach +action.detach.external.project.description=Detach selected external project # Notification notification.project.refresh.fail.description={0} ''{1}'' project refresh failed:\n{2} diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java index dacc4654e092..3e25602cb546 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/Key.java @@ -31,19 +31,45 @@ import java.io.Serializable; * @since 4/12/13 11:49 AM * @param data class */ -public class Key implements Serializable { +@SuppressWarnings("UnusedDeclaration") +public class Key implements Serializable, Comparable> { private static final long serialVersionUID = 1L; @NotNull private final String myDataClass; + + private final int myProcessingWeight; - public Key(@NotNull String dataClass) { + /** + * Creates new Key object. + * + * @param dataClass class of the payload data which will be associated with the current key + * @param processingWeight there is a possible case that when a {@link DataNode} object has children of more than on type (children + * with more than one different {@link Key} we might want to process one type of children before another. + * That's why we need a way to define that processing order. This parameter serves exactly for that - + * lower value means that key's payload should be processed before payload of the key with a greater + * value + */ + public Key(@NotNull String dataClass, int processingWeight) { myDataClass = dataClass; + myProcessingWeight = processingWeight; } @NotNull - public static Key create(@NotNull Class dataClass) { - return new Key(dataClass.getName()); + public static Key create(@NotNull Class dataClass, int processingWeight) { + return new Key(dataClass.getName(), processingWeight); + } + + /** + * There is a possible case that when a {@link DataNode} object has children of more than on type (children with more than + * one different {@link Key} we might want to process one type of children before another. That's why we need a way to define + * that processing order. This property serves exactly for that - lower value means that key's payload should be processed + * before payload of the key with a greater value. + * + * @return processing weight for data associated with the current key + */ + public int getProcessingWeight() { + return myProcessingWeight; } @Override @@ -63,6 +89,11 @@ public class Key implements Serializable { return true; } + @Override + public int compareTo(@NotNull Key that) { + return myProcessingWeight - that.myProcessingWeight; + } + @Override public String toString() { int i = myDataClass.lastIndexOf('.'); diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ProjectKeys.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ProjectKeys.java index 77d9df8c9151..64c6e6dd652d 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ProjectKeys.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ProjectKeys.java @@ -27,14 +27,14 @@ import org.jetbrains.annotations.NotNull; */ public class ProjectKeys { - @NotNull public static final Key PROJECT = Key.create(ProjectData.class); - @NotNull public static final Key MODULE = Key.create(ModuleData.class); - @NotNull public static final Key LIBRARY = Key.create(LibraryData.class); - @NotNull public static final Key CONTENT_ROOT = Key.create(ContentRootData.class); - @NotNull public static final Key MODULE_DEPENDENCY = Key.create(ModuleDependencyData.class); - @NotNull public static final Key LIBRARY_DEPENDENCY = Key.create(LibraryDependencyData.class); + @NotNull public static final Key PROJECT = Key.create(ProjectData.class, 50); + @NotNull public static final Key MODULE = Key.create(ModuleData.class, 70); + @NotNull public static final Key LIBRARY = Key.create(LibraryData.class, 90); + @NotNull public static final Key CONTENT_ROOT = Key.create(ContentRootData.class, 110); + @NotNull public static final Key MODULE_DEPENDENCY = Key.create(ModuleDependencyData.class, 130); + @NotNull public static final Key LIBRARY_DEPENDENCY = Key.create(LibraryDependencyData.class, 150); - @NotNull public static final Key TASK = Key.create(TaskData.class); + @NotNull public static final Key TASK = Key.create(TaskData.class, 250); private ProjectKeys() { } diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java index 88dca13e0e0a..eecd5540f5a7 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemLocalSettings.java @@ -15,9 +15,12 @@ */ package com.intellij.openapi.externalSystem.settings; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo; -import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; +import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.project.Project; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; @@ -58,6 +61,48 @@ public abstract class AbstractExternalSystemLocalSettings { ContainerUtilRt.>newHashMap() ); + @NotNull private final ProjectSystemId myExternalSystemId; + @NotNull private final Project myProject; + + protected AbstractExternalSystemLocalSettings(@NotNull ProjectSystemId externalSystemId, @NotNull Project project) { + myExternalSystemId = externalSystemId; + myProject = project; + } + + /** + * Asks current settings to drop all information related to external project which root config is located at the given path. + * + * @param linkedProjectPathsToForget target root external project's path + */ + public void forgetExternalProject(@NotNull Set linkedProjectPathsToForget) { + Map> projects = myAvailableProjects.get(); + for (Iterator>> it = projects.entrySet().iterator(); it.hasNext(); ) { + Map.Entry> entry = it.next(); + if (linkedProjectPathsToForget.contains(entry.getKey().getPath())) { + it.remove(); + } + } + + for (Iterator>> it = myAvailableTasks.get().entrySet().iterator(); it.hasNext(); ) { + Map.Entry> entry = it.next(); + if (linkedProjectPathsToForget.contains(entry.getKey()) + || linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(entry.getKey(), myExternalSystemId, myProject))) + { + it.remove(); + } + } + + for (Iterator it = myRecentTasks.get().iterator(); it.hasNext(); ) { + ExternalTaskExecutionInfo taskInfo = it.next(); + String path = taskInfo.getSettings().getExternalProjectPath(); + if (linkedProjectPathsToForget.contains(path) || + linkedProjectPathsToForget.contains(ExternalSystemApiUtil.getRootProjectPath(path, myExternalSystemId, myProject))) + { + it.remove(); + } + } + } + @SuppressWarnings("UnusedDeclaration") @NotNull public Map getExpandStates() { // Necessary for the serialization. diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java index ba6fc1504496..aff17a8e8aa7 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java @@ -55,6 +55,24 @@ public abstract class AbstractExternalSystemSettingstrue if there was an external project with the given config path linked to the current + * ide project; + * false otherwise + */ + public boolean unlinkExternalProject(@NotNull String linkedProjectPath) { + S removed = myLinkedProjectsSettings.remove(linkedProjectPath); + if (removed == null) { + return false; + } + + getPublisher().onProjectsUnlinked(Collections.singleton(linkedProjectPath)); + return true; + } + public void setLinkedProjectsSettings(@NotNull Collection settings) { List added = ContainerUtilRt.newArrayList(); Map removed = ContainerUtilRt.newHashMap(myLinkedProjectsSettings); diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListener.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListener.java index 8f9514c2921a..c15c384e29f6 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListener.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListener.java @@ -18,6 +18,7 @@ package com.intellij.openapi.externalSystem.settings; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Set; /** * Defines callback for external system settings change. @@ -31,7 +32,7 @@ public interface ExternalSystemSettingsListener settings); - void onProjectsUnlinked(@NotNull Collection linkedProjectPaths); + void onProjectsUnlinked(@NotNull Set linkedProjectPaths); void onUseAutoImportChange(boolean currentValue, @NotNull String linkedProjectPath); diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListenerAdapter.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListenerAdapter.java new file mode 100644 index 000000000000..a20bae9bee45 --- /dev/null +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalSystemSettingsListenerAdapter.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2013 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.settings; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Set; + +/** + * @author Denis Zhdanov + * @since 6/13/13 7:37 PM + */ +public class ExternalSystemSettingsListenerAdapter implements ExternalSystemSettingsListener { + + @Override + public void onProjectsLinked(@NotNull Collection settings) { + } + + @Override + public void onProjectsUnlinked(@NotNull Set linkedProjectPaths) { + } + + @Override + public void onUseAutoImportChange(boolean currentValue, @NotNull String linkedProjectPath) { + } + + @Override + public void onBulkChangeStart() { + } + + @Override + public void onBulkChangeEnd() { + } +} diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java index de2129f05aa2..3e41f1e290bf 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemApiUtil.java @@ -19,11 +19,13 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware; import com.intellij.openapi.externalSystem.ExternalSystemManager; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.Key; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.fileTypes.FileTypes; +import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; @@ -53,7 +55,8 @@ import java.util.regex.Pattern; */ public class ExternalSystemApiUtil { - private static final Logger LOG = Logger.getInstance("#" + ExternalSystemApiUtil.class.getName()); + private static final Logger LOG = + Logger.getInstance("#" + ExternalSystemApiUtil.class.getName()); private static final String LAST_USED_PROJECT_PATH_PREFIX = "LAST_EXTERNAL_PROJECT_PATH_"; @NotNull public static final String PATH_SEPARATOR = "/"; @@ -74,6 +77,7 @@ public class ExternalSystemApiUtil { }; @NotNull public static final Comparator ORDER_AWARE_COMPARATOR = new Comparator() { + @Override public int compare(Object o1, Object o2) { int order1 = getOrder(o1); @@ -100,6 +104,20 @@ public class ExternalSystemApiUtil { } }; + @NotNull private static final Function, Key> GROUPER = new Function, Key>() { + @Override + public Key fun(DataNode node) { + return node.getKey(); + } + }; + + @NotNull private static final Comparator COMPARABLE_GLUE = new Comparator() { + @SuppressWarnings("unchecked") + @Override + public int compare(Object o1, Object o2) { + return ((Comparable)o1).compareTo(o2); + } + }; private ExternalSystemApiUtil() { } @@ -192,18 +210,7 @@ public class ExternalSystemApiUtil { @NotNull public static Map, List>> group(@NotNull Collection> nodes) { - if (nodes.isEmpty()) { - return Collections.emptyMap(); - } - Map, List>> result = ContainerUtilRt.newHashMap(); - for (DataNode node : nodes) { - List> n = result.get(node.getKey()); - if (n == null) { - result.put(node.getKey(), n = ContainerUtilRt.newArrayList()); - } - n.add(node); - } - return result; + return groupBy(nodes, GROUPER); } @NotNull @@ -236,9 +243,19 @@ public class ExternalSystemApiUtil { } grouped.add(data); } + + if (!result.isEmpty() && result.keySet().iterator().next() instanceof Comparable) { + List ordered = ContainerUtilRt.newArrayList(result.keySet()); + Collections.sort(ordered, COMPARABLE_GLUE); + Map> orderedResult = ContainerUtilRt.newLinkedHashMap(); + for (K k : ordered) { + orderedResult.put(k, result.get(k)); + } + return orderedResult; + } return result; } - + @SuppressWarnings("unchecked") @NotNull public static Collection> getChildren(@NotNull DataNode node, @NotNull Key key) { @@ -388,4 +405,32 @@ public class ExternalSystemApiUtil { buffer.insert(0, rootProjectDir.getName()); return buffer.toString(); } + + /** + * There is a possible case that external project linked to an ide project is a multi-project, i.e. contains more than one + * module. + *

+ * This method tries to find root project's config path assuming that given path points to a sub-project's config path. + * + * @param externalProjectPath external sub-project's config path + * @param externalSystemId target external system + * @param project target ide project + * @return root external project's path if given path is considered to point to a known sub-project's config; + * null if it's not possible to find a root project's config path on the basis of the + * given path + */ + @Nullable + public static String getRootProjectPath(@NotNull String externalProjectPath, + @NotNull ProjectSystemId externalSystemId, + @NotNull Project project) + { + ExternalSystemManager manager = getManager(externalSystemId); + if (manager == null) { + return null; + } + if (manager instanceof ExternalSystemAutoImportAware) { + return ((ExternalSystemAutoImportAware)manager).getAffectedExternalProjectPath(externalProjectPath, project); + } + return null; + } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java new file mode 100644 index 000000000000..dfd9c2e3ef24 --- /dev/null +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/DetachExternalProjectAction.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2013 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.action; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.externalSystem.ExternalSystemManager; +import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; +import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; +import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemRecentTasksList; +import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemTasksTreeModel; +import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings; +import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; +import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; +import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.util.Collections; + +/** + * @author Denis Zhdanov + * @since 6/13/13 5:42 PM + */ +public class DetachExternalProjectAction extends AnAction implements DumbAware { + + public DetachExternalProjectAction() { + getTemplatePresentation().setText(ExternalSystemBundle.message("action.detach.external.project.text")); + getTemplatePresentation().setDescription(ExternalSystemBundle.message("action.detach.external.project.description")); + } + + @Override + public void update(AnActionEvent e) { + MyInfo info = getProcessingInfo(e.getDataContext()); + if (info.icon != null) { + e.getPresentation().setIcon(info.icon); + } + e.getPresentation().setVisible(info.externalProject != null); + } + + @Override + public void actionPerformed(AnActionEvent e) { + MyInfo info = getProcessingInfo(e.getDataContext()); + if (info.settings == null || info.localSettings == null || info.externalProject == null) { + return; + } + + ExternalSystemTasksTreeModel allTasksModel = ExternalSystemDataKeys.ALL_TASKS_MODEL.getData(e.getDataContext()); + if (allTasksModel != null) { + allTasksModel.pruneNodes(info.externalProject); + } + + ExternalSystemRecentTasksList recentTasksList = ExternalSystemDataKeys.RECENT_TASKS_LIST.getData(e.getDataContext()); + if (recentTasksList != null) { + recentTasksList.getModel().forgetTasksFrom(info.externalProject.getPath()); + } + + info.localSettings.forgetExternalProject(Collections.singleton(info.externalProject.getPath())); + info.settings.unlinkExternalProject(info.externalProject.getPath()); + } + + @NotNull + private static MyInfo getProcessingInfo(@NotNull DataContext context) { + ExternalProjectPojo externalProject = ExternalSystemDataKeys.SELECTED_PROJECT.getData(context); + if (externalProject == null) { + return MyInfo.EMPTY; + } + + ProjectSystemId externalSystemId = ExternalSystemDataKeys.EXTERNAL_SYSTEM_ID.getData(context); + if (externalSystemId == null) { + return MyInfo.EMPTY; + } + + Project ideProject = PlatformDataKeys.PROJECT.getData(context); + if (ideProject == null) { + return MyInfo.EMPTY; + } + + ExternalSystemManager manager = ExternalSystemApiUtil.getManager(externalSystemId); + assert manager != null; + AbstractExternalSystemSettings settings = manager.getSettingsProvider().fun(ideProject); + ExternalProjectSettings externalProjectSettings = settings.getLinkedProjectSettings(externalProject.getPath()); + AbstractExternalSystemLocalSettings localSettings = manager.getLocalSettingsProvider().fun(ideProject); + Icon icon = ExternalSystemUiUtil.getUiAware(externalSystemId).getProjectIcon(); + return new MyInfo(externalProjectSettings == null ? null : settings, + localSettings == null ? null : localSettings, + externalProjectSettings == null ? null : externalProject, + icon); + } + + private static class MyInfo { + + public static final MyInfo EMPTY = new MyInfo(null, null, null, null); + + @Nullable public final AbstractExternalSystemSettings settings; + @Nullable public final AbstractExternalSystemLocalSettings localSettings; + @Nullable public final ExternalProjectPojo externalProject; + @Nullable public final Icon icon; + + MyInfo(@Nullable AbstractExternalSystemSettings settings, + @Nullable AbstractExternalSystemLocalSettings localSettings, + @Nullable ExternalProjectPojo externalProject, + @Nullable Icon icon) + { + this.settings = settings; + this.localSettings = localSettings; + this.externalProject = externalProject; + this.icon = icon; + } + } +} diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/ExternalSystemDataKeys.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/ExternalSystemDataKeys.java index 4d4359940111..cb485c326396 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/ExternalSystemDataKeys.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/ExternalSystemDataKeys.java @@ -18,6 +18,7 @@ package com.intellij.openapi.externalSystem.model; import com.intellij.notification.NotificationGroup; import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; +import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemRecentTasksList; import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemTasksTreeModel; import org.jetbrains.annotations.NotNull; @@ -32,6 +33,7 @@ public class ExternalSystemDataKeys { @NotNull public static final DataKey NOTIFICATION_GROUP = DataKey.create("external.system.notification"); @NotNull public static final DataKey ALL_TASKS_MODEL = DataKey.create("external.system.all.tasks.model"); @NotNull public static final DataKey SELECTED_TASK = DataKey.create("external.system.selected.task"); + @NotNull public static final DataKey SELECTED_PROJECT = DataKey.create("external.system.selected.project"); @NotNull public static final DataKey RECENT_TASKS_LIST = DataKey.create("external.system.recent.tasks.list"); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java index 6f6902654429..266b3bb5d33b 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskSettingsControl.java @@ -69,8 +69,9 @@ public class ExternalSystemTaskSettingsControl implements ExternalSystemSettings @Override public void fillUi(@NotNull final PaintAwarePanel canvas, int indentLevel) { - myProjectPathLabel = - new JBLabel(ExternalSystemBundle.message("run.configuration.settings.label.project", myExternalSystemId.getReadableName())); + myProjectPathLabel = new JBLabel(ExternalSystemBundle.message( + "run.configuration.settings.label.project", myExternalSystemId.getReadableName() + )); ExternalSystemManager manager = ExternalSystemApiUtil.getManager(myExternalSystemId); FileChooserDescriptor projectPathChooserDescriptor = null; if (manager instanceof ExternalSystemUiAware) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTaskListModel.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTaskListModel.java index e82d4bbc790f..5e739ba1227a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTaskListModel.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTaskListModel.java @@ -15,7 +15,11 @@ */ package com.intellij.openapi.externalSystem.service.task.ui; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; +import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; +import com.intellij.openapi.project.Project; import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; @@ -28,6 +32,16 @@ import java.util.List; */ public class ExternalSystemRecentTaskListModel extends DefaultListModel { + @NotNull private final ProjectSystemId myExternalSystemId; + @NotNull private final Project myProject; + + public ExternalSystemRecentTaskListModel(@NotNull ProjectSystemId externalSystemId, @NotNull Project project) { + myExternalSystemId = externalSystemId; + myProject = project; + ensureSize(ExternalSystemConstants.RECENT_TASKS_NUMBER); + } + + @SuppressWarnings("unchecked") public void setTasks(@NotNull List tasks) { clear(); List tasksToUse = ContainerUtilRt.newArrayList(tasks); @@ -36,6 +50,7 @@ public class ExternalSystemRecentTaskListModel extends DefaultListModel { } } + @SuppressWarnings("unchecked") public void setFirst(@NotNull ExternalTaskExecutionInfo task) { insertElementAt(task, 0); if (size() > 1) { @@ -44,9 +59,10 @@ public class ExternalSystemRecentTaskListModel extends DefaultListModel { for (int i = 1; i < size(); i++) { if (task.equals(getElementAt(i))) { remove(i); - return; + break; } } + ensureSize(ExternalSystemConstants.RECENT_TASKS_NUMBER); } @NotNull @@ -61,6 +77,7 @@ public class ExternalSystemRecentTaskListModel extends DefaultListModel { return result; } + @SuppressWarnings("unchecked") public void ensureSize(int elementsNumber) { int toAdd = elementsNumber - size(); if (toAdd <= 0) { @@ -71,6 +88,26 @@ public class ExternalSystemRecentTaskListModel extends DefaultListModel { } } + /** + * Asks current model to remove all 'recent task info' entries which point to tasks from external project with the given path. + * + * @param externalProjectPath target external project's path + */ + public void forgetTasksFrom(@NotNull String externalProjectPath) { + for (int i = size() - 1; i >= 0; i--) { + Object e = getElementAt(i); + if (e instanceof ExternalTaskExecutionInfo) { + String path = ((ExternalTaskExecutionInfo)e).getSettings().getExternalProjectPath(); + if (externalProjectPath.equals(path) + || externalProjectPath.equals(ExternalSystemApiUtil.getRootProjectPath(path, myExternalSystemId, myProject))) + { + removeElementAt(i); + } + } + } + ensureSize(ExternalSystemConstants.RECENT_TASKS_NUMBER); + } + static class MyEmptyDescriptor { } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTasksList.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTasksList.java index cc179911266b..9dd416f0b72e 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTasksList.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/task/ui/ExternalSystemRecentTasksList.java @@ -66,7 +66,6 @@ public class ExternalSystemRecentTasksList extends JBList implements Producer(new ExternalSystemNodeDescriptor("", "", null))); myExternalSystemId = externalSystemId; - ExternalSystemManager manager = ExternalSystemApiUtil.getManager(externalSystemId); - if (manager instanceof ExternalSystemUiAware) { - myUiAware = (ExternalSystemUiAware)manager; - } - else { - myUiAware = DefaultExternalSystemUiAware.INSTANCE; - } + myUiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); } private static String getTaskName(@NotNull ExternalTaskExecutionInfo taskInfo) { @@ -120,6 +111,27 @@ public class ExternalSystemTasksTreeModel extends DefaultTreeModel { return result; } + /** + * Asks current model to remove all nodes which have given data as a {@link ExternalSystemNodeDescriptor#getElement() payload}. + * + * @param payload target payload + */ + public void pruneNodes(@NotNull Object payload) { + Deque> toProcess = new ArrayDeque>(); + toProcess.addFirst(getRoot()); + while (!toProcess.isEmpty()) { + ExternalSystemNode node = toProcess.removeLast(); + if (payload.equals(node.getDescriptor().getElement())) { + removeNodeFromParent(node); + } + else { + for (int i = 0; i < node.getChildCount(); i++) { + toProcess.addFirst(node.getChildAt(i)); + } + } + } + } + public void ensureSubProjectsStructure(@NotNull ExternalProjectPojo topLevelProject, @NotNull Collection subProjects) { @@ -162,6 +174,9 @@ public class ExternalSystemTasksTreeModel extends DefaultTreeModel { } public void ensureTasks(@NotNull String externalProjectConfigPath, @NotNull Collection tasks) { + if (tasks.isEmpty()) { + return; + } ExternalSystemNode moduleNode = findProjectNode(externalProjectConfigPath); if (moduleNode == null) { LOG.warn(String.format( @@ -186,7 +201,7 @@ public class ExternalSystemTasksTreeModel extends DefaultTreeModel { } } } - + if (!toAdd.isEmpty()) { for (ExternalTaskExecutionInfo taskInfo : toAdd) { moduleNode.add(new ExternalSystemNode(descriptor(taskInfo, myUiAware.getTaskIcon()))); diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java index a7c1ca2e2013..4e8e245f3433 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectPathField.java @@ -31,6 +31,7 @@ import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemTasksTr import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemBundle; +import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.Project; @@ -166,13 +167,7 @@ public class ExternalProjectPathField extends ComponentWithBrowseButton manager = ExternalSystemApiUtil.getManager(externalSystemId); assert manager != null; final AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(project); - final ExternalSystemUiAware uiAware; - if (manager instanceof ExternalSystemUiAware) { - uiAware = (ExternalSystemUiAware)manager; - } - else { - uiAware = DefaultExternalSystemUiAware.INSTANCE; - } + final ExternalSystemUiAware uiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); TextFieldCompletionProvider provider = new TextFieldCompletionProviderDumbAware() { @Override protected void addCompletionVariants(@NotNull String text, int offset, @NotNull String prefix, @NotNull CompletionResultSet result) { @@ -224,13 +219,7 @@ public class ExternalProjectPathField extends ComponentWithBrowseButton manager = ExternalSystemApiUtil.getManager(externalSystemId); assert manager != null; final AbstractExternalSystemLocalSettings settings = manager.getLocalSettingsProvider().fun(project); - final ExternalSystemUiAware uiAware; - if (manager instanceof ExternalSystemUiAware) { - uiAware = (ExternalSystemUiAware)manager; - } - else { - uiAware = DefaultExternalSystemUiAware.INSTANCE; - } + final ExternalSystemUiAware uiAware = ExternalSystemUiUtil.getUiAware(externalSystemId); String rawText = editor.getDocument().getText(); for (Map.Entry> entry : settings.getAvailableProjects().entrySet()) { diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUiUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUiUtil.java index 7e90a3828002..80f482fe994a 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUiUtil.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUiUtil.java @@ -16,9 +16,13 @@ package com.intellij.openapi.externalSystem.util; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.externalSystem.ExternalSystemManager; +import com.intellij.openapi.externalSystem.ExternalSystemUiAware; +import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo; import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo; import com.intellij.openapi.externalSystem.service.task.ui.ExternalSystemTasksTreeModel; +import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; @@ -179,4 +183,10 @@ public class ExternalSystemUiUtil { } } } + + @NotNull + public static ExternalSystemUiAware getUiAware(@NotNull ProjectSystemId externalSystemId) { + ExternalSystemManager manager = ExternalSystemApiUtil.getManager(externalSystemId); + return manager instanceof ExternalSystemUiAware ? (ExternalSystemUiAware)manager : DefaultExternalSystemUiAware.INSTANCE; + } } diff --git a/platform/platform-resources/src/idea/ExternalSystemActions.xml b/platform/platform-resources/src/idea/ExternalSystemActions.xml index bfe6fe7ebeeb..8c96e3f5fd71 100644 --- a/platform/platform-resources/src/idea/ExternalSystemActions.xml +++ b/platform/platform-resources/src/idea/ExternalSystemActions.xml @@ -12,6 +12,8 @@ + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java index 33f2ae934481..b0aa3664a384 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleSettingsListenerAdapter.java @@ -1,17 +1,18 @@ package org.jetbrains.plugins.gradle.config; +import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.settings.GradleProjectSettings; import org.jetbrains.plugins.gradle.settings.GradleSettingsListener; -import java.util.Collection; - /** * @author Denis Zhdanov * @since 3/13/12 3:53 PM */ -public abstract class GradleSettingsListenerAdapter implements GradleSettingsListener { +public abstract class GradleSettingsListenerAdapter extends ExternalSystemSettingsListenerAdapter + implements GradleSettingsListener +{ @Override public void onGradleHomeChange(@Nullable String oldPath, @Nullable String newPath, @NotNull String linkedProjectPath) { @@ -24,24 +25,4 @@ public abstract class GradleSettingsListenerAdapter implements GradleSettingsLis @Override public void onServiceDirectoryPathChange(@Nullable String oldPath, @Nullable String newPath) { } - - @Override - public void onProjectsLinked(@NotNull Collection settings) { - } - - @Override - public void onProjectsUnlinked(@NotNull Collection linkedProjectPaths) { - } - - @Override - public void onUseAutoImportChange(boolean currentValue, @NotNull String linkedProjectPath) { - } - - @Override - public void onBulkChangeStart() { - } - - @Override - public void onBulkChangeEnd() { - } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java index 4d5b8032cf04..9db445ce7313 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleToolWindowPanel.java @@ -5,14 +5,12 @@ import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SideBorder; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.settings.GradleSettings; import org.jetbrains.plugins.gradle.settings.GradleSettingsListener; import org.jetbrains.plugins.gradle.ui.RichTextControlBuilder; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleLocalSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleLocalSettings.java index d4dd83dd8d8e..3da23b6c2c46 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleLocalSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleLocalSettings.java @@ -5,6 +5,7 @@ import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalS import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.util.GradleConstants; /** * @author Denis Zhdanov @@ -15,6 +16,10 @@ public class GradleLocalSettings extends AbstractExternalSystemLocalSettings implements PersistentStateComponent { + public GradleLocalSettings(@NotNull Project project) { + super(GradleConstants.SYSTEM_ID, project); + } + @NotNull public static GradleLocalSettings getInstance(@NotNull Project project) { return ServiceManager.getService(project, GradleLocalSettings.class);