| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * 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.android.tools.idea.actions; |
| |
| import com.android.tools.idea.gradle.parser.BuildFileKey; |
| import com.android.tools.idea.gradle.parser.Dependency; |
| import com.android.tools.idea.gradle.parser.GradleBuildFile; |
| import com.android.tools.idea.gradle.parser.GradleSettingsFile; |
| import com.android.tools.idea.gradle.project.GradleProjectImporter; |
| import com.android.tools.idea.gradle.util.Projects; |
| import com.intellij.ide.projectView.actions.MarkLibraryRootAction; |
| import com.intellij.openapi.actionSystem.AnAction; |
| import com.intellij.openapi.actionSystem.AnActionEvent; |
| import com.intellij.openapi.actionSystem.CommonDataKeys; |
| import com.intellij.openapi.actionSystem.Presentation; |
| import com.intellij.openapi.application.AccessToken; |
| import com.intellij.openapi.application.Result; |
| import com.intellij.openapi.application.WriteAction; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleManager; |
| import com.intellij.openapi.module.ModuleUtilCore; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.roots.ProjectFileIndex; |
| import com.intellij.openapi.roots.ProjectRootManager; |
| import com.intellij.openapi.roots.libraries.ui.OrderRoot; |
| import com.intellij.openapi.roots.libraries.ui.impl.RootDetectionUtil; |
| import com.intellij.application.options.ModulesComboBox; |
| import com.intellij.openapi.roots.ui.configuration.libraryEditor.DefaultLibraryRootsComponentDescriptor; |
| import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryNameAndLevelPanel; |
| import com.intellij.openapi.ui.DialogWrapper; |
| import com.intellij.openapi.util.io.FileUtilRt; |
| import com.intellij.openapi.vfs.JarFileSystem; |
| import com.intellij.openapi.vfs.VfsUtilCore; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.ui.SortedListModel; |
| import com.intellij.util.ui.FormBuilder; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| /** |
| * Replaces the {@linkplain MarkLibraryRootAction} for Android-Gradle projects. This action, given an input of a number of |
| * {@linkplain VirtualFile} instances, examines them to see if they are jarfiles and could be added to a library as a dependency. |
| * If so, the action displays a dialog allowing the user to choose a module to add the jars to, and updates the module's build.gradle. |
| * <p> |
| * For non-Android-Gradle projects, this action delegates to MarkLibraryRootAction. |
| */ |
| public class CreateLibraryFromFilesAction extends AnAction { |
| AnAction myDelegate = new MarkLibraryRootAction(); |
| |
| public CreateLibraryFromFilesAction() { |
| super("Add As Library..."); |
| } |
| |
| @Override |
| public void actionPerformed(@NotNull AnActionEvent e) { |
| final Project project = getEventProject(e); |
| if (project == null) return; |
| |
| if (!Projects.requiresAndroidModel(project)) { |
| myDelegate.actionPerformed(e); |
| return; |
| } |
| |
| final List<VirtualFile> jars = getRoots(e); |
| if (jars.isEmpty()) { |
| return; |
| } |
| |
| final List<OrderRoot> roots = RootDetectionUtil.detectRoots(jars, null, project, new DefaultLibraryRootsComponentDescriptor()); |
| new CreateGradleLibraryFromFilesDialog(project, roots).show(); |
| } |
| |
| @Override |
| public void update(@NotNull AnActionEvent e) { |
| final Project project = getEventProject(e); |
| boolean visible = false; |
| if (project != null && ModuleManager.getInstance(project).getModules().length > 0) { |
| final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); |
| for (VirtualFile root : getRoots(e)) { |
| if (!root.isInLocalFileSystem() && FileUtilRt.extensionEquals(root.getName(), "jar") && !fileIndex.isInLibraryClasses(root)) { |
| visible = true; |
| break; |
| } |
| } |
| } |
| |
| Presentation presentation = e.getPresentation(); |
| presentation.setVisible(visible); |
| presentation.setEnabled(visible); |
| } |
| |
| @NotNull |
| private static List<VirtualFile> getRoots(@NotNull AnActionEvent e) { |
| final Project project = getEventProject(e); |
| final VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY); |
| if (project == null || files == null || files.length == 0) { |
| return Collections.emptyList(); |
| } |
| |
| List<VirtualFile> roots = new ArrayList<VirtualFile>(); |
| for (VirtualFile file : files) { |
| VirtualFile root = JarFileSystem.getInstance().getJarRootForLocalFile(file); |
| if (root != null) { |
| roots.add(root); |
| } |
| } |
| return roots; |
| } |
| |
| private static class CreateGradleLibraryFromFilesDialog extends DialogWrapper { |
| public static final String COMMAND_TITLE = "Create Library"; |
| private final ModulesComboBox myModulesComboBox; |
| private final Project myProject; |
| private final JPanel myPanel; |
| private final List<OrderRoot> myRoots; |
| private GradleSettingsFile mySettingsFile; |
| |
| public CreateGradleLibraryFromFilesDialog(@NotNull Project project, @NotNull List<OrderRoot> roots) { |
| super(project, true); |
| setTitle(COMMAND_TITLE); |
| myProject = project; |
| myRoots = roots; |
| mySettingsFile = GradleSettingsFile.get(myProject); |
| |
| final FormBuilder builder = LibraryNameAndLevelPanel.createFormBuilder(); |
| myModulesComboBox = new ModulesComboBox(); |
| myModulesComboBox.fillModules(myProject); |
| myModulesComboBox.setSelectedModule(findModule(roots)); |
| for (Iterator iter = ((SortedListModel)myModulesComboBox.getModel()).iterator(); iter.hasNext(); ) { |
| Module module = (Module)iter.next(); |
| String path = GradleSettingsFile.getModuleGradlePath(module); |
| if (path == null || !mySettingsFile.hasBuildFile(path)) { |
| iter.remove(); |
| } |
| } |
| builder.addLabeledComponent("&Add to module:", myModulesComboBox); |
| myPanel = builder.getPanel(); |
| init(); |
| } |
| |
| @Nullable |
| private Module findModule(List<OrderRoot> roots) { |
| for (OrderRoot root : roots) { |
| Module module = null; |
| final VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(root.getFile()); |
| if (local != null) { |
| module = ModuleUtilCore.findModuleForFile(local, myProject); |
| } |
| if (module == null) { |
| module = ModuleUtilCore.findModuleForFile(root.getFile(), myProject); |
| } |
| if (module != null) { |
| return module; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| protected void doOKAction() { |
| AccessToken token = WriteAction.start(); |
| try { |
| final Module module = myModulesComboBox.getSelectedModule(); |
| if (module == null) { return; } |
| String moduleGradlePath = GradleSettingsFile.getModuleGradlePath(module); |
| if (moduleGradlePath == null) { return; } |
| final GradleBuildFile buildFile = mySettingsFile.getModuleBuildFile(moduleGradlePath); |
| List<Dependency> value = (List<Dependency>)buildFile.getValue(BuildFileKey.DEPENDENCIES); |
| final List<Dependency> dependencies = value != null ? value : new ArrayList<Dependency>(); |
| boolean added = false; |
| for (OrderRoot root : myRoots) { |
| VirtualFile parent = buildFile.getFile().getParent(); |
| final VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(root.getFile()); |
| if (local != null) { |
| String path = VfsUtilCore.getRelativePath(local, parent, '/'); |
| if (path == null) { |
| path = local.getPath(); |
| } |
| Dependency newDependency = new Dependency(Dependency.Scope.COMPILE, Dependency.Type.FILES, path); |
| if (!dependencies.contains(newDependency)) { |
| dependencies.add((newDependency)); |
| added = true; |
| } |
| } |
| if (added) { |
| new WriteCommandAction<Void>(myProject, COMMAND_TITLE, buildFile.getPsiFile()) { |
| @Override |
| protected void run(@NotNull Result<Void> result) throws Throwable { |
| buildFile.setValue(BuildFileKey.DEPENDENCIES, dependencies); |
| } |
| }.execute(); |
| } |
| } |
| } |
| finally { |
| token.finish(); |
| } |
| GradleProjectImporter.getInstance().requestProjectSync(myProject, null); |
| super.doOKAction(); |
| } |
| |
| @Override |
| protected JComponent createCenterPanel() { |
| return myPanel; |
| } |
| } |
| } |