package com.intellij.lang.javascript.flex.actions.addAsLib; import com.intellij.flex.model.bc.LinkageType; import com.intellij.icons.AllIcons; import com.intellij.lang.javascript.flex.FlexBundle; import com.intellij.lang.javascript.flex.actions.FlexBCTree; import com.intellij.lang.javascript.flex.library.FlexLibraryProperties; import com.intellij.lang.javascript.flex.library.FlexLibraryType; import com.intellij.lang.javascript.flex.projectStructure.FlexBuildConfigurationsExtension; import com.intellij.lang.javascript.flex.projectStructure.model.*; import com.intellij.lang.javascript.flex.projectStructure.model.impl.FlexProjectConfigurationEditor; import com.intellij.lang.javascript.flex.projectStructure.options.FlexProjectRootsUtil; import com.intellij.lang.javascript.flex.projectStructure.ui.CompositeConfigurable; import com.intellij.lang.javascript.flex.projectStructure.ui.DependenciesConfigurable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.impl.libraries.ApplicationLibraryTable; import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.components.JBList; import com.intellij.ui.navigation.Place; import com.intellij.util.IconUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.*; import java.util.List; public class AddAsSwcLibDialog extends DialogWrapper { private final Project myProject; private final List<VirtualFile> myRoots; private JPanel myMainPanel; private FlexBCTree myBCTree; private JBList myLibComponentsList; private JCheckBox myOpenProjectStructureCheckBox; public AddAsSwcLibDialog(final @NotNull Project project, final @Nullable Module preferredModule, final List<VirtualFile> roots) { super(project); myProject = project; myRoots = roots; setTitle(FlexBundle.message("add.as.library.title")); if (preferredModule != null) { final FlexBuildConfiguration bc = FlexBuildConfigurationManager.getInstance(preferredModule).getActiveConfiguration(); myBCTree.selectRow(preferredModule, bc); } myLibComponentsList.setModel(JBList.createDefaultListModel(roots.toArray(new VirtualFile[roots.size()]))); myLibComponentsList.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final JLabel component = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); final VirtualFile file = (VirtualFile)value; component.setText(FileUtil.toSystemDependentName(file.getPath())); if (file.isDirectory() && file.isInLocalFileSystem()) { component.setIcon(AllIcons.Nodes.JarDirectory); } else { final VirtualFile localFile = JarFileSystem.getInstance().getLocalVirtualFileFor(file); if (localFile != null) { component.setText(FileUtil.toSystemDependentName(localFile.getPath())); component.setIcon(IconUtil.getIcon(localFile, 0, null)); } } return component; } }); myLibComponentsList.setVisibleRowCount(myLibComponentsList.getItemsCount()); init(); } @Override @Nullable protected JComponent createCenterPanel() { return myMainPanel; } @Override @Nullable public JComponent getPreferredFocusedComponent() { return myBCTree; } private void createUIComponents() { myBCTree = new FlexBCTree(myProject); myBCTree.setCheckedStatusForAll(false); myBCTree.setVisibleRowCount(Math.min(myBCTree.getRowCount(), 15)); } @Override @Nullable protected ValidationInfo doValidate() { if (myBCTree.getSelectedBCs().isEmpty()) { return new ValidationInfo("No build configurations selected"); } return null; } @Override protected void doOKAction() { final Collection<Pair<Module, FlexBuildConfiguration>> modulesAndBCs = myBCTree.getSelectedBCs(); final Map<Module, ModifiableRootModel> moduleToModifiableModelMap = new THashMap<>(); for (Pair<Module, FlexBuildConfiguration> moduleAndBC : modulesAndBCs) { moduleToModifiableModelMap.put(moduleAndBC.first, ModuleRootManager.getInstance(moduleAndBC.first).getModifiableModel()); } final LibraryTable.ModifiableModel projectLibsModel = ProjectLibraryTable.getInstance(myProject).getModifiableModel(); final LibraryTable.ModifiableModel globalLibsModel = ApplicationLibraryTable.getApplicationTable().getModifiableModel(); final FlexProjectConfigurationEditor flexConfigEditor = FlexProjectConfigurationEditor.createEditor(myProject, moduleToModifiableModelMap, projectLibsModel, globalLibsModel); addLib(flexConfigEditor, modulesAndBCs, myRoots); try { flexConfigEditor.commit(); } catch (ConfigurationException e) { Logger.getInstance(AddAsSwcLibDialog.class).error(e); } ApplicationManager.getApplication().runWriteAction(() -> { globalLibsModel.commit(); projectLibsModel.commit(); for (ModifiableRootModel modifiableRootModel : moduleToModifiableModelMap.values()) { modifiableRootModel.commit(); } }); if (myOpenProjectStructureCheckBox.isSelected()) { final Pair<Module, FlexBuildConfiguration> moduleAndBc = modulesAndBCs.iterator().next(); openProjectStructure(moduleAndBc.first, moduleAndBc.second); } super.doOKAction(); } private static void addLib(final FlexProjectConfigurationEditor flexConfigEditor, final Collection<Pair<Module, FlexBuildConfiguration>> modulesAndBCs, final List<VirtualFile> roots) { for (Pair<Module, FlexBuildConfiguration> moduleAndBc : modulesAndBCs) { final Module module = moduleAndBc.first; ModifiableFlexBuildConfiguration bc = null; final ModifiableFlexBuildConfiguration[] bcs = flexConfigEditor.getConfigurations(module); for (ModifiableFlexBuildConfiguration each : bcs) { if (each.getName().equals(moduleAndBc.second.getName())) { bc = each; break; } } if (bc == null) continue; final Collection<VirtualFile> filteredRoots = filterAlreadyExistingRoots(roots, flexConfigEditor, module, bc); final LibraryTable.ModifiableModel libraryModel = flexConfigEditor.getLibraryModel(bc.getDependencies()); for (VirtualFile file : filteredRoots) { final Library library = libraryModel.createLibrary(null, FlexLibraryType.FLEX_LIBRARY); final LibraryEx.ModifiableModelEx libraryModifiableModel = ((LibraryEx.ModifiableModelEx)library.getModifiableModel()); final String libraryId = UUID.randomUUID().toString(); libraryModifiableModel.setProperties(new FlexLibraryProperties(libraryId)); if (file.isInLocalFileSystem() && file.isDirectory()) { libraryModifiableModel.addJarDirectory(file, false); } else { libraryModifiableModel.addRoot(file, OrderRootType.CLASSES); } ApplicationManager.getApplication().runWriteAction(() -> libraryModifiableModel.commit()); final ModifiableModuleLibraryEntry libraryEntry = flexConfigEditor.createModuleLibraryEntry(bc.getDependencies(), libraryId); libraryEntry.getDependencyType().setLinkageType(LinkageType.Merged); bc.getDependencies().getModifiableEntries().add(libraryEntry); } } } private static Collection<VirtualFile> filterAlreadyExistingRoots(final Collection<VirtualFile> roots, final FlexProjectConfigurationEditor flexConfigEditor, final Module module, final ModifiableFlexBuildConfiguration bc) { final Set<VirtualFile> result = new THashSet<>(roots); final DependencyEntry[] entries = bc.getDependencies().getEntries(); for (DependencyEntry entry : entries) { if (entry instanceof ModifiableModuleLibraryEntry) { final LibraryOrderEntry orderEntry = FlexProjectRootsUtil .findOrderEntry((ModuleLibraryEntry)entry, flexConfigEditor.getModifiableRootModel(module)); if (orderEntry != null) { for (VirtualFile file : orderEntry.getRootFiles(OrderRootType.CLASSES)) { if (result.contains(file)) { result.remove(file); } } } } else if (entry instanceof ModifiableSharedLibraryEntry) { final Library library = FlexProjectRootsUtil.findOrderEntry(module.getProject(), (SharedLibraryEntry)entry); if (library != null) { for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) { if (result.contains(file)) { result.remove(file); } } } } } return result; } private void openProjectStructure(final Module module, final FlexBuildConfiguration bc) { ApplicationManager.getApplication().invokeLater(() -> { final ProjectStructureConfigurable configurable = ProjectStructureConfigurable.getInstance(myProject); ShowSettingsUtil.getInstance().editConfigurable(myProject, configurable, () -> { final Place place = FlexBuildConfigurationsExtension.getInstance().getConfigurator() .getPlaceFor(module, bc.getName()) .putPath(CompositeConfigurable.TAB_NAME, DependenciesConfigurable.TAB_NAME); configurable.navigateTo(place, true); }); }); } }