diff --git a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java
index 5db53a0c3157..8198230777a4 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/SimpleToolWindowPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2012 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.
@@ -24,6 +24,7 @@ import com.intellij.ui.switcher.QuickActionProvider;
import com.intellij.util.ui.AwtVisitor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -87,6 +88,7 @@ public class SimpleToolWindowPanel extends JPanel implements QuickActionProvider
repaint();
}
+ @Nullable
public Object getData(@NonNls String dataId) {
return QuickActionProvider.KEY.is(dataId) && myProvideQuickActions ? this : null;
}
diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties
index 205b4ac96bb6..e85e37d53385 100644
--- a/plugins/gradle/resources/i18n/GradleBundle.properties
+++ b/plugins/gradle/resources/i18n/GradleBundle.properties
@@ -77,6 +77,8 @@ gradle.action.refresh.project.text=Refresh gradle project
gradle.action.refresh.project.description=Allows to force linked gradle project refresh
gradle.action.open.script.text=Open linked gradle project
gradle.action.open.script.description=Allows to open project file of the linked gradle project at the editor
+gradle.action.import.entity.text=Import
+gradle.action.import.entity.description=Import target gradle entity
gradle.settings.color.text.sample.conflict.node.name=node-with-conflicting-setup
gradle.settings.color.text.sample.node.sync.name=node-with-same-setup
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index ca35a79bc1eb..ff4374eb52a2 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -34,17 +34,25 @@
-
-
+
-
+
+
+
+
+
+
+
+
+
+
@@ -72,10 +80,14 @@
+
+
+
+
\ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleImportEntityAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleImportEntityAction.java
new file mode 100644
index 000000000000..5000c5995b7e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/action/GradleImportEntityAction.java
@@ -0,0 +1,131 @@
+package org.jetbrains.plugins.gradle.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.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
+import org.jetbrains.plugins.gradle.importing.GradleModuleDependencyImporter;
+import org.jetbrains.plugins.gradle.importing.GradleModuleImporter;
+import org.jetbrains.plugins.gradle.model.GradleLibraryDependency;
+import org.jetbrains.plugins.gradle.model.GradleLibraryDependencyId;
+import org.jetbrains.plugins.gradle.model.GradleModule;
+import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
+import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
+import org.jetbrains.plugins.gradle.util.GradleBundle;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Imports target {@link GradleTextAttributes#GRADLE_LOCAL_CHANGE 'gradle local'} entity to the current intellij project.
+ *
+ * Not thread-safe.
+ *
+ * @author Denis Zhdanov
+ * @since 2/7/12 10:32 AM
+ */
+public class GradleImportEntityAction extends AnAction {
+
+ private static final Logger LOG = Logger.getInstance("#" + GradleImportEntityAction.class.getName());
+
+ public GradleImportEntityAction() {
+ getTemplatePresentation().setText(GradleBundle.message("gradle.action.import.entity.text"));
+ getTemplatePresentation().setDescription(GradleBundle.message("gradle.action.import.entity.description"));
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ final Collection> nodes = getInterestedNodes(e.getDataContext());
+ e.getPresentation().setEnabled(!nodes.isEmpty());
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
+ if (project == null) {
+ LOG.warn("Can't import gradle-local entities. Reason: target intellij project is undefined");
+ return;
+ }
+
+ final Collection> nodes = getInterestedNodes(e.getDataContext());
+
+ // We need to import not only the selected nodes but their gradle-local parents as well.
+ List> nodesToImport = new ArrayList>();
+ for (GradleProjectStructureNode> node : nodes) {
+ collectHierarchyToImport(node, nodesToImport);
+ }
+
+ GradleProjectStructureHelper projectStructureHelper = project.getComponent(GradleProjectStructureHelper.class);
+ GradleModuleImporter moduleImporter = ServiceManager.getService(GradleModuleImporter.class);
+ GradleModuleDependencyImporter dependencyImporter = ServiceManager.getService(GradleModuleDependencyImporter.class);
+
+ for (GradleProjectStructureNode> node : nodesToImport) {
+ switch (node.getType()) {
+ case MODULE:
+ final GradleModule gradleModule = projectStructureHelper.findGradleModuleByName(node.getDescriptor().getName());
+ if (gradleModule != null) {
+ moduleImporter.importModule(gradleModule, project);
+ }
+ break;
+ case LIBRARY_DEPENDENCY:
+ final Object element = node.getDescriptor().getElement();
+ if (!(element instanceof GradleLibraryDependencyId)) {
+ break;
+ }
+ GradleLibraryDependencyId id = (GradleLibraryDependencyId)element;
+ final GradleLibraryDependency dependency = projectStructureHelper.findLibraryDependency(id);
+ final Module intellijModule = projectStructureHelper.findIntellijModuleByName(id.getModuleName());
+ if (dependency != null && intellijModule != null) {
+ dependencyImporter.importDependency(dependency, intellijModule);
+ }
+ break;
+ default: // Do nothing
+ }
+ }
+ }
+
+ /**
+ * When particular gradle-local node is asked to be imported we need to import its gradle-local parent hierarchy as well.
+ *
+ * This method allows to collect all parent nodes of the given nodes that should be imported as well.
+ *
+ * Note: those nodes are added to the given collection starting from the topmost one.
+ *
+ * @param node target node
+ * @param storage target nodes storage
+ */
+ private static void collectHierarchyToImport(@Nullable GradleProjectStructureNode> node,
+ @NotNull Collection> storage)
+ {
+ if (node == null || node.getDescriptor().getAttributes() != GradleTextAttributes.GRADLE_LOCAL_CHANGE) {
+ return;
+ }
+ collectHierarchyToImport(node.getParent(), storage);
+ storage.add(node);
+ }
+
+ @NotNull
+ private static Collection> getInterestedNodes(@NotNull DataContext context) {
+ final Collection> selectedNodes = GradleDataKeys.SYNC_TREE_NODE.getData(context);
+ if (selectedNodes == null) {
+ return Collections.emptyList();
+ }
+ List> result = new ArrayList>();
+ for (GradleProjectStructureNode> node : selectedNodes) {
+ if (node.getDescriptor().getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE) {
+ result.add(node);
+ }
+ }
+ return result;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java
index 529fea913a98..bc8c9302a5a3 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacade.java
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.diff;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEntry;
+import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
@@ -28,6 +29,9 @@ import java.util.Collection;
*/
public interface PlatformFacade {
+ @NotNull
+ LibraryTable getProjectLibraryTable(@NotNull Project project);
+
@NotNull
LanguageLevel getLanguageLevel(@NotNull Project project);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java
index b4a82429a169..84ae46eda4a4 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/PlatformFacadeImpl.java
@@ -8,6 +8,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
+import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
+import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -24,6 +26,12 @@ import java.util.Collection;
*/
public class PlatformFacadeImpl implements PlatformFacade {
+ @NotNull
+ @Override
+ public LibraryTable getProjectLibraryTable(@NotNull Project project) {
+ return ProjectLibraryTable.getInstance(project);
+ }
+
@NotNull
@Override
public LanguageLevel getLanguageLevel(@NotNull Project project) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java
new file mode 100644
index 000000000000..16e0baf4b191
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java
@@ -0,0 +1,16 @@
+package org.jetbrains.plugins.gradle.importing;
+
+import com.intellij.openapi.module.Module;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.GradleContentRoot;
+
+/**
+ * @author Denis Zhdanov
+ * @since 2/7/12 3:20 PM
+ */
+public class GradleContentRootImporter {
+
+ public void importContentRoots(@NotNull Iterable contentRoots, @NotNull Module module) {
+ // TODO den implement
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleDependencyImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleDependencyImporter.java
new file mode 100644
index 000000000000..ada5a3a5d389
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleDependencyImporter.java
@@ -0,0 +1,152 @@
+package org.jetbrains.plugins.gradle.importing;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.libraries.Library;
+import com.intellij.openapi.roots.libraries.LibraryTable;
+import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.diff.PlatformFacade;
+import org.jetbrains.plugins.gradle.model.*;
+import org.jetbrains.plugins.gradle.util.GradleLog;
+
+import java.io.File;
+import java.util.*;
+
+/**
+ * @author Denis Zhdanov
+ * @since 2/7/12 3:23 PM
+ */
+public class GradleModuleDependencyImporter {
+
+ private static final Map LIBRARY_ROOT_MAPPINGS
+ = new EnumMap(LibraryPathType.class);
+ static {
+ LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.BINARY, OrderRootType.CLASSES);
+ LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.SOURCE, OrderRootType.SOURCES);
+ LIBRARY_ROOT_MAPPINGS.put(LibraryPathType.DOC, JavadocOrderRootType.getInstance());
+ assert LibraryPathType.values().length == LIBRARY_ROOT_MAPPINGS.size();
+ }
+
+ @NotNull private final PlatformFacade myPlatformFacade;
+
+ public GradleModuleDependencyImporter(@NotNull PlatformFacade platformFacade) {
+ myPlatformFacade = platformFacade;
+ }
+
+ public void importDependency(@NotNull GradleDependency dependency, @NotNull Module module) {
+ importDependencies(Collections.singleton(dependency), module);
+ }
+
+ public void importDependencies(@NotNull Iterable dependencies, @NotNull Module module) {
+ final List moduleDependencies = new ArrayList();
+ final List libraryDependencies = new ArrayList();
+ GradleEntityVisitor visitor = new GradleEntityVisitorAdapter() {
+ @Override
+ public void visit(@NotNull GradleModuleDependency dependency) {
+ moduleDependencies.add(dependency);
+ }
+
+ @Override
+ public void visit(@NotNull GradleLibraryDependency dependency) {
+ libraryDependencies.add(dependency);
+ }
+ };
+ for (GradleDependency dependency : dependencies) {
+ dependency.invite(visitor);
+ }
+ importLibraryDependencies(libraryDependencies, module);
+ importModuleDependencies(moduleDependencies, module);
+ }
+
+ public void importModuleDependencies(@NotNull Iterable dependencies, @NotNull Module module) {
+ // TODO den implement
+ }
+
+ public void importLibraryDependencies(@NotNull final Iterable dependencies, @NotNull final Module module) {
+ // TODO den make non-EDT agnostic
+ final LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(module.getProject());
+ final Map gradle2intellij = new HashMap();
+ final Set librariesToCreate = new HashSet();
+ for (final GradleLibraryDependency dependency : dependencies) {
+ // Try to find existing library in project libraries.
+ Library library = libraryTable.getLibraryByName(dependency.getName());
+ if (library == null) {
+ librariesToCreate.add(dependency.getTarget());
+ }
+ else {
+ gradle2intellij.put(dependency.getTarget(), library);
+ }
+ }
+
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ // Create all necessary libraries.
+ if (!librariesToCreate.isEmpty()) {
+ final LibraryTable.ModifiableModel projectLibraryModel = libraryTable.getModifiableModel();
+ try {
+ for (GradleLibrary library : librariesToCreate) {
+ final Library intellijLibrary = projectLibraryModel.createLibrary(library.getName());
+ gradle2intellij.put(library, intellijLibrary);
+ final Library.ModifiableModel libraryModel = intellijLibrary.getModifiableModel();
+ try {
+ registerPaths(library, libraryModel);
+ }
+ finally {
+ libraryModel.commit();
+ }
+ }
+ }
+ finally {
+ projectLibraryModel.commit();
+ }
+ }
+
+ // Register library dependencies.
+ ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+ final ModifiableRootModel moduleRootModel = moduleRootManager.getModifiableModel();
+ try {
+ for (GradleLibraryDependency dependency : dependencies) {
+ LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(gradle2intellij.get(dependency.getTarget()));
+ orderEntry.setExported(dependency.isExported());
+ orderEntry.setScope(dependency.getScope());
+ }
+ }
+ finally {
+ moduleRootModel.commit();
+ }
+ // TODO den refresh gradle project tree
+ }
+ });
+ }
+
+ private static void registerPaths(@NotNull GradleLibrary gradleLibrary, @NotNull Library.ModifiableModel model) {
+ for (LibraryPathType pathType : LibraryPathType.values()) {
+ for (String path : gradleLibrary.getPaths(pathType)) {
+ VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(new File(path));
+ if (virtualFile == null) {
+ GradleLog.LOG.warn(String.format("Can't find %s of the library '%s' at path '%s'", pathType, gradleLibrary.getName(), path));
+ continue;
+ }
+ if (virtualFile.isDirectory()) {
+ model.addRoot(virtualFile, LIBRARY_ROOT_MAPPINGS.get(pathType));
+ }
+ else {
+ VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
+ if (jarRoot == null) {
+ GradleLog.LOG.warn(String.format(
+ "Can't parse contents of the jar file at path '%s' for the library '%s''", path, gradleLibrary.getName()
+ ));
+ continue;
+ }
+ model.addRoot(jarRoot, LIBRARY_ROOT_MAPPINGS.get(pathType));
+ }
+ }
+ }
+ }
+
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleImporter.java
new file mode 100644
index 000000000000..7ee3a1eac434
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModuleImporter.java
@@ -0,0 +1,125 @@
+package org.jetbrains.plugins.gradle.importing;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.StdModuleTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.Alarm;
+import com.intellij.util.containers.hash.HashMap;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.GradleModule;
+import org.jetbrains.plugins.gradle.util.GradleLog;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Encapsulates functionality of importing gradle module to the intellij project.
+ *
+ * @author Denis Zhdanov
+ * @since 2/7/12 2:49 PM
+ */
+public class GradleModuleImporter {
+
+ /**
+ * We can't modify project modules (add/remove) until it's initialised, so, we delay that activity. Current constant
+ * holds number of milliseconds to wait between 'after project initialisation' processing attempts.
+ */
+ private static final int PROJECT_INITIALISATION_DELAY_MS = (int)TimeUnit.SECONDS.toMillis(1);
+
+ private final Alarm myAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
+
+ @NotNull private final GradleContentRootImporter myContentRootImporter;
+ @NotNull private final GradleModuleDependencyImporter myDependencyImporter;
+
+ public GradleModuleImporter(@NotNull GradleContentRootImporter contentRootImporter,
+ @NotNull GradleModuleDependencyImporter dependencyImporter)
+ {
+ myContentRootImporter = contentRootImporter;
+ myDependencyImporter = dependencyImporter;
+ }
+
+ public void importModule(@NotNull GradleModule module, @NotNull Project project) {
+ importModules(Collections.singleton(module), project, false);
+ }
+
+ public void importModules(@NotNull final Iterable modules, @NotNull final Project project, final boolean recursive) {
+ if (!project.isInitialized()) {
+ myAlarm.addRequest(new ImportModulesTask(project, modules, recursive), PROJECT_INITIALISATION_DELAY_MS);
+ return;
+ }
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ removeExistingModulesConfigs(modules);
+ Application application = ApplicationManager.getApplication();
+ final Map moduleMappings = new HashMap();
+ application.runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final ModuleManager moduleManager = ModuleManager.getInstance(project);
+ for (GradleModule module : modules) {
+ final Module created = moduleManager.newModule(module.getModuleFilePath(), StdModuleTypes.JAVA);
+ moduleMappings.put(module, created);
+ }
+ }
+ });
+ if (!recursive) {
+ return;
+ }
+ for (GradleModule gradleModule : modules) {
+ final Module intellijModule = moduleMappings.get(gradleModule);
+ myContentRootImporter.importContentRoots(gradleModule.getContentRoots(), intellijModule);
+ myDependencyImporter.importDependencies(gradleModule.getDependencies(), intellijModule);
+ }
+ }
+ });
+ }
+
+ private static void removeExistingModulesConfigs(@NotNull Iterable modules) {
+ for (GradleModule module : modules) {
+ // Remove existing '*.iml' file if necessary.
+ final String moduleFilePath = module.getModuleFilePath();
+ File file = new File(moduleFilePath);
+ if (file.isFile()) {
+ boolean success = file.delete();
+ if (!success) {
+ GradleLog.LOG.warn("Can't remove existing module file at '" + moduleFilePath + "'");
+ }
+ }
+ }
+ }
+
+ private class ImportModulesTask implements Runnable {
+
+ private final Project myProject;
+ private final Iterable myModules;
+ private final boolean myRecursive;
+
+ ImportModulesTask(@NotNull Project project, @NotNull Iterable modules, boolean recursive) {
+ myProject = project;
+ myModules = modules;
+ myRecursive = recursive;
+ }
+
+ @Override
+ public void run() {
+ myAlarm.cancelAllRequests();
+ if (!myProject.isInitialized()) {
+ myAlarm.addRequest(
+ new ImportModulesTask(myProject, myModules, myRecursive),
+ PROJECT_INITIALISATION_DELAY_MS
+ );
+ return;
+ }
+
+ importModules(myModules, myProject, myRecursive);
+ }
+ }
+
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java
index 0753b80c148f..5a6de37bf1d0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java
@@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
* @author Denis Zhdanov
* @since 8/26/11 10:01 AM
*/
+// TODO den remove
public class GradleModulesImporter {
private static final Map LIBRARY_ROOT_MAPPINGS
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java
index 4d6fb05e6100..f9bd8e7d8f6f 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java
@@ -260,7 +260,7 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza
// We build tree node, its settings control and map them altogether. The only trick here is that nodes can reuse the same
// settings control (e.g. more than one node may have the same library as a dependency, so, library dependency node for
// every control will use the same settings control).
- GradleProjectStructureNode result = new GradleProjectStructureNode(myFactory.buildDescriptor(entity));
+ GradleProjectStructureNode result = new GradleProjectStructureNode(myFactory.buildDescriptor(entity), GradleEntityType.SYNTHETIC);
Pair> pair = processed.get(entity);
if (pair == null) {
String cardName = String.valueOf(counter);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleProjectStructureFactory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleProjectStructureFactory.java
index 95989623ae96..fef410ddc578 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleProjectStructureFactory.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleProjectStructureFactory.java
@@ -138,7 +138,7 @@ public class GradleProjectStructureFactory {
return;
}
for (GradleProjectStructureNode node : treeNodes) {
- node.getDescriptor().setText(evt.getNewValue().toString());
+ node.getDescriptor().setName(evt.getNewValue().toString());
model.nodeChanged(node);
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependency.java
index cc6558f17909..a20b775c2a06 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependency.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependency.java
@@ -15,6 +15,9 @@ public interface GradleDependency extends GradleEntity {
@NotNull
DependencyScope getScope();
+
+ @NotNull
+ GradleModule getOwnerModule();
@NotNull
GradleDependency clone(@NotNull GradleEntityCloneContext context);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleEntityType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleEntityType.java
new file mode 100644
index 000000000000..948903544476
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleEntityType.java
@@ -0,0 +1,9 @@
+package org.jetbrains.plugins.gradle.model;
+
+/**
+ * @author Denis Zhdanov
+ * @since 2/7/12 11:18 AM
+ */
+public enum GradleEntityType {
+ PROJECT, MODULE, LIBRARY_DEPENDENCY, SYNTHETIC
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
index 72c5e424f100..ee03292076d2 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java
@@ -1,20 +1,27 @@
package org.jetbrains.plugins.gradle.sync;
+import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.project.Project;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.GradleToolWindowPanel;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
+import org.jetbrains.plugins.gradle.ui.GradleDataKeys;
+import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
/**
* UI control for showing difference between the gradle and intellij project structure.
@@ -24,6 +31,7 @@ import java.util.Collection;
*/
public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
+ private Tree myTree;
private GradleProjectStructureTreeModel myTreeModel;
private JPanel myContent;
@@ -52,14 +60,16 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
private void init() {
myContent = new JPanel(new GridBagLayout());
myTreeModel = new GradleProjectStructureTreeModel(getProject(), getProjectFacade(), getProjectStructureHelper());
- Tree tree = new Tree(myTreeModel);
- applyInitialAppearance(tree, (DefaultMutableTreeNode)myTreeModel.getRoot());
+ myTree = new Tree(myTreeModel);
+ applyInitialAppearance(myTree, (DefaultMutableTreeNode)myTreeModel.getRoot());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.weightx = constraints.weighty = 1;
- myContent.add(tree, constraints);
- myContent.setBackground(tree.getBackground());
+ myContent.add(myTree, constraints);
+ myContent.setBackground(myTree.getBackground());
+
+ CustomizationUtil.installPopupHandler(myTree, GradleConstants.ACTION_GROUP_SYNC_TREE, GradleConstants.SYNC_TREE_PLACE);
}
@NotNull
@@ -75,6 +85,25 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
int i = 1;
}
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (GradleDataKeys.SYNC_TREE_NODE.is(dataId)) {
+ TreePath[] paths = myTree.getSelectionPaths();
+ if (paths == null) {
+ return null;
+ }
+ List> result = new ArrayList>();
+ for (TreePath path : paths) {
+ result.add((GradleProjectStructureNode>)path.getLastPathComponent());
+ }
+ return result;
+ }
+ else {
+ return super.getData(dataId);
+ }
+ }
+
private static void applyInitialAppearance(@NotNull Tree tree, @NotNull DefaultMutableTreeNode node) {
if (node.getUserObject() == GradleProjectStructureTreeModel.DEPENDENCIES_NODE_DESCRIPTOR) {
tree.expandPath(new TreePath(node.getPath()));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
index 96b2c8d8ece0..8fba1b558e74 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureHelper.java
@@ -8,6 +8,7 @@ import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.RootPolicy;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.diff.PlatformFacade;
import org.jetbrains.plugins.gradle.model.*;
@@ -37,20 +38,20 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* false otherwise
*/
public boolean isIntellijLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
- for (Module module : myFacade.getModules(myProject)) {
- if (!id.getModuleName().equals(module.getName())) {
- continue;
+ final Module module = findIntellijModuleByName(id.getModuleName());
+ if (module == null) {
+ return false;
+ }
+
+ RootPolicy visitor = new RootPolicy() {
+ @Override
+ public Boolean visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Boolean value) {
+ return id.getLibraryName().equals(libraryOrderEntry.getLibraryName());
}
- RootPolicy visitor = new RootPolicy() {
- @Override
- public Boolean visitLibraryOrderEntry(LibraryOrderEntry libraryOrderEntry, Boolean value) {
- return id.getLibraryName().equals(libraryOrderEntry.getLibraryName());
- }
- };
- for (OrderEntry entry : myFacade.getOrderEntries(module)) {
- if (entry.accept(visitor, false)) {
- return true;
- }
+ };
+ for (OrderEntry entry : myFacade.getOrderEntries(module)) {
+ if (entry.accept(visitor, false)) {
+ return true;
}
}
return false;
@@ -64,29 +65,55 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
* false otherwise
*/
public boolean isGradleLibraryDependencyExist(@NotNull final GradleLibraryDependencyId id) {
+ return findLibraryDependency(id) != null;
+ }
+
+ @Nullable
+ public Module findIntellijModuleByName(@NotNull String name) {
+ for (Module module : myFacade.getModules(myProject)) {
+ if (name.equals(module.getName())) {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public GradleModule findGradleModuleByName(@NotNull String name) {
final GradleProject project = myModel.getGradleProject();
if (project == null) {
- return false;
+ return null;
}
- final Ref matched = new Ref();
+ for (GradleModule module : project.getModules()) {
+ if (name.equals(module.getName())) {
+ return module;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public GradleLibraryDependency findLibraryDependency(@NotNull final GradleLibraryDependencyId id) {
+ final GradleModule module = findGradleModuleByName(id.getModuleName());
+ if (module == null) {
+ return null;
+ }
+ final Ref ref = new Ref();
GradleEntityVisitor visitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleLibraryDependency dependency) {
- matched.set(id.getLibraryName().equals(dependency.getName()));
- }
- };
- for (GradleModule module : project.getModules()) {
- if (!id.getModuleName().equals(module.getName())) {
- continue;
- }
- for (GradleDependency dependency : module.getDependencies()) {
- dependency.invite(visitor);
- if (matched.get()) {
- return true;
+ if (id.getLibraryName().equals(dependency.getName())) {
+ ref.set(dependency);
}
}
- return false;
+ };
+ for (GradleDependency dependency : module.getDependencies()) {
+ dependency.invite(visitor);
+ final GradleLibraryDependency result = ref.get();
+ if (result != null) {
+ return result;
+ }
}
- return false;
+ return null;
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
index 9374826609b2..9a32b95e3338 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureTreeModel.java
@@ -10,6 +10,7 @@ import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.diff.*;
+import org.jetbrains.plugins.gradle.model.GradleEntityType;
import org.jetbrains.plugins.gradle.model.GradleLibraryDependencyId;
import org.jetbrains.plugins.gradle.ui.GradleIcons;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
@@ -77,7 +78,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
myModuleDependencies.clear();
myModules.clear();
- GradleProjectStructureNode root = buildNode(getProject(), getProject().getName(), myPlatformFacade.getProjectIcon());
+ GradleProjectStructureNode root
+ = buildNode(getProject(), GradleEntityType.PROJECT, getProject().getName(), myPlatformFacade.getProjectIcon());
final Collection modules = myPlatformFacade.getModules(getProject());
RootPolicy policy = new RootPolicy() {
@Override
@@ -86,7 +88,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
};
for (Module module : modules) {
- final GradleProjectStructureNode moduleNode = buildNode(module.getName(), GradleIcons.MODULE_ICON);
+ final GradleProjectStructureNode moduleNode = buildNode(GradleEntityType.MODULE, module.getName(), GradleIcons.MODULE_ICON);
myModules.put(module.getName(), moduleNode); // Assuming that module names are unique.
List libraryDependencies = new ArrayList();
for (OrderEntry orderEntry : myPlatformFacade.getOrderEntries(module)) {
@@ -100,7 +102,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
if (id == null) {
continue;
}
- dependenciesNode.add(buildNode(id, id.getLibraryName(), GradleIcons.LIB_ICON));
+ dependenciesNode.add(buildNode(id, GradleEntityType.LIBRARY_DEPENDENCY, id.getLibraryName(), GradleIcons.LIB_ICON));
}
moduleNode.add(dependenciesNode);
}
@@ -119,14 +121,18 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return new GradleProjectStructureNodeDescriptor(entity, name, icon);
}
- private static GradleProjectStructureNode buildNode(@NotNull String name, @NotNull Icon icon) {
- return buildNode(name, name, icon);
+ private static GradleProjectStructureNode buildNode(@NotNull GradleEntityType type, @NotNull String name, @NotNull Icon icon) {
+ return buildNode(name, type, name, icon);
}
- private static GradleProjectStructureNode buildNode(@NotNull T entity, @NotNull String name, @NotNull Icon icon) {
- return new GradleProjectStructureNode(buildDescriptor(entity, name, icon));
+ private static GradleProjectStructureNode buildNode(@NotNull T entity,
+ @NotNull GradleEntityType type,
+ @NotNull String name,
+ @NotNull Icon icon)
+ {
+ return new GradleProjectStructureNode(buildDescriptor(entity, name, icon), type);
}
-
+
private GradleProjectStructureNode getDependenciesNode(@NotNull String moduleName) {
final GradleProjectStructureNode cached = myModuleDependencies.get(moduleName);
if (cached != null) {
@@ -134,11 +140,11 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
GradleProjectStructureNode moduleNode = myModules.get(moduleName);
if (moduleNode == null) {
- moduleNode = buildNode(moduleName, GradleIcons.MODULE_ICON);
+ moduleNode = buildNode(GradleEntityType.MODULE, moduleName, GradleIcons.MODULE_ICON);
myModules.put(moduleName, moduleNode);
}
- GradleProjectStructureNode result = new GradleProjectStructureNode(DEPENDENCIES_NODE_DESCRIPTOR);
+ GradleProjectStructureNode result = new GradleProjectStructureNode(DEPENDENCIES_NODE_DESCRIPTOR, GradleEntityType.SYNTHETIC);
moduleNode.add(result);
myModuleDependencies.put(moduleName, result);
@@ -184,7 +190,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return;
}
}
- GradleProjectStructureNode newNode = buildNode(id, id.getLibraryName(), GradleIcons.LIB_ICON);
+ GradleProjectStructureNode newNode
+ = buildNode(id, GradleEntityType.LIBRARY_DEPENDENCY, id.getLibraryName(), GradleIcons.LIB_ICON);
newNode.getDescriptor().setAttributes(attributes);
dependenciesNode.add(newNode);
nodeStructureChanged(dependenciesNode);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java
new file mode 100644
index 000000000000..134db91a6efc
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleDataKeys.java
@@ -0,0 +1,18 @@
+package org.jetbrains.plugins.gradle.ui;
+
+import com.intellij.openapi.actionSystem.DataKey;
+
+import java.util.Collection;
+
+/**
+ * @author Denis Zhdanov
+ * @since 2/7/12 11:19 AM
+ */
+public class GradleDataKeys {
+
+ /** Key for obtaining currently selected nodes at the gradle 'sync project structure' tree. */
+ public static final DataKey>> SYNC_TREE_NODE = DataKey.create("gradle.sync.tree.node");
+
+ private GradleDataKeys() {
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java
index 2551a3162a2e..e009d1a88b19 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNode.java
@@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.ui;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
+import org.jetbrains.plugins.gradle.model.GradleEntityType;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.MutableTreeNode;
@@ -16,11 +17,14 @@ import java.util.*;
public class GradleProjectStructureNode extends DefaultMutableTreeNode implements Iterable> {
private final Set myConflictChanges = new HashSet();
- private final GradleProjectStructureNodeDescriptor myDescriptor;
- public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor descriptor) {
+ private final GradleProjectStructureNodeDescriptor myDescriptor;
+ private final GradleEntityType myType;
+
+ public GradleProjectStructureNode(@NotNull GradleProjectStructureNodeDescriptor descriptor, @NotNull GradleEntityType type) {
super(descriptor);
myDescriptor = descriptor;
+ myType = type;
}
@NotNull
@@ -28,6 +32,11 @@ public class GradleProjectStructureNode extends DefaultMutableTreeNode implem
return myDescriptor;
}
+ @NotNull
+ public GradleEntityType getType() {
+ return myType;
+ }
+
@Override
public GradleProjectStructureNode> getChildAt(int index) {
return (GradleProjectStructureNode)super.getChildAt(index);
@@ -41,10 +50,10 @@ public class GradleProjectStructureNode extends DefaultMutableTreeNode implem
@Override
public void add(MutableTreeNode newChild) {
GradleProjectStructureNode> child = (GradleProjectStructureNode)newChild;
- final String newText = child.getDescriptor().getText();
+ final String newName = child.getDescriptor().getName();
for (int i = 0; i < getChildCount(); i++) {
GradleProjectStructureNode> node = getChildAt(i);
- if (newText.compareTo(node.getDescriptor().getText()) < 0) {
+ if (newName.compareTo(node.getDescriptor().getName()) < 0) {
insert(newChild, i);
return;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeDescriptor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeDescriptor.java
index 6fe8baa490f0..031e5077fa2e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeDescriptor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeDescriptor.java
@@ -46,12 +46,7 @@ public class GradleProjectStructureNodeDescriptor extends PresentableNodeDesc
return myData;
}
- @NotNull
- public String getText() {
- return myName;
- }
-
- public void setText(@NotNull String name) {
+ public void setName(@NotNull String name) {
myName = name;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
index 49f441744592..acc24a256475 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
@@ -1,10 +1,7 @@
package org.jetbrains.plugins.gradle.util;
-import com.intellij.openapi.util.IconLoader;
import org.jetbrains.annotations.NonNls;
-import javax.swing.*;
-
/**
* Holds object representation of icons used at the Gradle plugin.
*
@@ -13,9 +10,13 @@ import javax.swing.*;
*/
public class GradleConstants {
- @NonNls public static final String EXTENSION = "gradle";
- @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
+ @NonNls public static final String EXTENSION = "gradle";
+ @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle";
+
@NonNls public static final String TOOL_WINDOW_TOOLBAR_PLACE = "GRADLE_SYNC_CHANGES_TOOLBAR";
+ @NonNls public static final String SYNC_TREE_PLACE = "GRADLE_SYNC_TREE_PLACE";
+
+ @NonNls public static final String ACTION_GROUP_SYNC_TREE = "Gradle.SyncTreeGroup";
private GradleConstants() {
}