package com.google.jstestdriver.idea.assertFramework.support; import com.google.common.collect.Lists; import com.google.jstestdriver.idea.assertFramework.library.JsLibraryHelper; import com.intellij.lang.javascript.library.JSLibraryMappings; import com.intellij.openapi.application.WriteAction; 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 com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.IdeBorderFactory; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.SwingHelper; import com.intellij.util.ui.UIUtil; import com.intellij.webcore.ScriptingFrameworkDescriptor; import com.intellij.webcore.libraries.ScriptingLibraryMappings; import com.intellij.webcore.libraries.ScriptingLibraryModel; import com.intellij.webcore.libraries.ui.ModuleScopeSelectionView; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.Arrays; import java.util.List; public class ChooseScopeAndCreateLibraryDialog extends DialogWrapper { private static final Logger LOG = Logger.getInstance(ChooseScopeAndCreateLibraryDialog.class); private final Project myProject; private final ModuleScopeSelectionView myModuleSelector; private final JTextField myLibraryNameTextField; private final JPanel myComponent; private final JsLibraryHelper myLibraryHelper; public ChooseScopeAndCreateLibraryDialog(@NotNull Project project, @NotNull String desiredLibraryName, @NotNull List<VirtualFile> libraryFiles, @NotNull ScriptingFrameworkDescriptor frameworkDescriptor, @Nullable VirtualFile requestor, boolean warnAboutOutsideCode) { super(project); myProject = project; myLibraryHelper = new JsLibraryHelper(myProject, desiredLibraryName, libraryFiles, frameworkDescriptor); setTitle("Coding Assistance For " + desiredLibraryName); myModuleSelector = new ModuleScopeSelectionView(project, requestor, true, true); myLibraryNameTextField = createTextField(myLibraryHelper); List<Component> components = Lists.newArrayList(); if (!myLibraryHelper.hasReusableLibraryModel()) { components.addAll(Arrays.asList( createDescription(warnAboutOutsideCode), Box.createVerticalStrut(10) )); } components.addAll(Arrays.asList( createLibraryNamePanel(), Box.createVerticalStrut(5), createCompletionPanel() )); myComponent = SwingHelper.newLeftAlignedVerticalPanel(components); super.init(); } private static JTextField createTextField(JsLibraryHelper helper) { JTextField textField = new JTextField(helper.getJsLibraryName()); textField.setEnabled(!helper.hasReusableLibraryModel()); Dimension prefSize = textField.getPreferredSize(); textField.setPreferredSize(new Dimension((int) (prefSize.width * 1.2), prefSize.height)); return textField; } private static JComponent createDescription(boolean warnAboutOutsideCode) { List<Component> components = Lists.newArrayList(); if (warnAboutOutsideCode) { JLabel warnLabel = new JLabel(UIUtil.getBalloonWarningIcon()); warnLabel.setText(" Added files have been placed outside of the project."); components.add(warnLabel); components.add(Box.createVerticalStrut(10)); } components.add(new JLabel("JavaScript library will be created to provide coding assistance.")); return SwingHelper.newLeftAlignedVerticalPanel(components); } @NotNull private JPanel createCompletionPanel() { JPanel completionPanel = new JPanel(new BorderLayout()); completionPanel.add(myModuleSelector.getComponent(), BorderLayout.CENTER); completionPanel.setBorder(IdeBorderFactory.createTitledBorder("Code completion")); return completionPanel; } @NotNull private Component createLibraryNamePanel() { JPanel libraryNamePanel = new JPanel(new GridBagLayout()); libraryNamePanel.add(new JLabel("Library name:"), new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new JBInsets(0, 0, 0, 5), 0, 0 )); libraryNamePanel.add(myLibraryNameTextField, new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, JBUI.emptyInsets(), 0, 0 )); return libraryNamePanel; } @Override protected JComponent createCenterPanel() { return myComponent; } @Override public ValidationInfo doValidate() { if (myLibraryHelper.hasReusableLibraryModel()) { return null; } String text= myLibraryNameTextField.getText(); if (StringUtil.isEmpty(text)) { return new ValidationInfo("Library name is empty", myLibraryNameTextField); } boolean exists = myLibraryHelper.doesJavaScriptLibraryModelExist(myLibraryNameTextField.getText()); if (exists) { return new ValidationInfo("Library with such name already exists", myLibraryNameTextField); } return null; } @Override protected void doOKAction() { ErrorMessage errorMessage = WriteAction.compute(() -> createLibraryAndAssociate()); if (errorMessage != null) { Messages.showErrorDialog(errorMessage.getDescription(), "Adding " + myLibraryHelper.getJsLibraryName()); LOG.warn(errorMessage.getDescription(), errorMessage.getThrowable()); } super.doOKAction(); } @Nullable private ErrorMessage createLibraryAndAssociate() { String libraryName = myLibraryNameTextField.getText(); ScriptingLibraryModel libraryModel = myLibraryHelper.getOrCreateJsLibraryModel(libraryName); try { ScriptingLibraryMappings libraryMappings = ServiceManager.getService(myProject, JSLibraryMappings.class); if (myModuleSelector.isAssociateWithProjectView()) { if (myModuleSelector.isAssociateWithProjectRequested()) { libraryMappings.associateWithProject(libraryModel.getName()); LOG.info("Library '" + libraryModel.getName() + "' has been successfully associated with the project"); } else { libraryMappings.disassociateWithProject(libraryModel.getName()); } } else { for (Module module : myModuleSelector.getSelectedModules()) { ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); VirtualFile[] roots = moduleRootManager.getContentRoots(); for (VirtualFile root : roots) { libraryMappings.associate(root, libraryModel.getName(), false); LOG.info("Library '" + libraryModel.getName() + "' has been associated with " + root); } } } myLibraryHelper.commit(); return null; } catch (Exception ex) { return new ErrorMessage("Unable to associate '" + libraryName + "' JavaScript library", ex); } } private static class ErrorMessage { private final String myDescription; private final Throwable myThrowable; private ErrorMessage(@NotNull String description, @Nullable Throwable throwable) { myDescription = description; myThrowable = throwable; } @NotNull public String getDescription() { return myDescription; } @Nullable public Throwable getThrowable() { return myThrowable; } } }