package com.scss.settings;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.ide.actions.ShowSettingsUtilImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiManager;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.TextFieldWithHistory;
import com.intellij.ui.TextFieldWithHistoryWithBrowseButton;
import com.intellij.util.NotNullProducer;
import com.intellij.util.ui.SwingHelper;
import com.intellij.util.ui.UIUtil;
import com.scss.ScssLintProjectComponent;
import com.scss.utils.ScssLintFinder;
import com.scss.utils.ScssLintRunner;
import com.wix.settings.ValidationUtils;
import com.wix.settings.Validator;
import com.wix.ui.PackagesNotificationPanel;
import com.wix.utils.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.util.List;
public class ScssLintSettingsPage implements Configurable {
private static final String FIX_IT = "Fix it";
private static final String HOW_TO_USE_SCSS_LINT = "How to Use SCSS Lint";
private static final String HOW_TO_USE_LINK = "https://github.com/idok/scss-lint-plugin";
private final Project project;
private JCheckBox pluginEnabledCheckbox;
private JPanel panel;
private JPanel errorPanel;
private TextFieldWithHistoryWithBrowseButton scssLintConfigFile;
private JRadioButton searchForConfigInRadioButton;
private JRadioButton useSpecificConfigRadioButton;
private HyperlinkLabel usageLink;
private JLabel ScssLintConfigFilePathLabel;
private JCheckBox treatAllIssuesCheckBox;
private JLabel versionLabel;
private JLabel scssLintExeLabel;
private TextFieldWithHistoryWithBrowseButton scssLintExeField;
private final PackagesNotificationPanel packagesNotificationPanel;
public ScssLintSettingsPage(@NotNull final Project project) {
this.project = project;
configESLintBinField();
configScssLintConfigField();
this.packagesNotificationPanel = new PackagesNotificationPanel(project);
errorPanel.add(this.packagesNotificationPanel.getComponent(), BorderLayout.CENTER);
}
private void addListeners() {
useSpecificConfigRadioButton.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
scssLintConfigFile.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
}
});
pluginEnabledCheckbox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
boolean enabled = e.getStateChange() == ItemEvent.SELECTED;
setEnabledState(enabled);
}
});
DocumentAdapter docAdp = new DocumentAdapter() {
protected void textChanged(DocumentEvent e) {
updateLaterInEDT();
}
};
scssLintExeField.getChildComponent().getTextEditor().getDocument().addDocumentListener(docAdp);
scssLintConfigFile.getChildComponent().getTextEditor().getDocument().addDocumentListener(docAdp);
}
private void updateLaterInEDT() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
ScssLintSettingsPage.this.update();
}
});
}
private void update() {
ApplicationManager.getApplication().assertIsDispatchThread();
validate();
}
private void setEnabledState(boolean enabled) {
searchForConfigInRadioButton.setEnabled(enabled);
useSpecificConfigRadioButton.setEnabled(enabled);
scssLintConfigFile.setEnabled(enabled && useSpecificConfigRadioButton.isSelected());
scssLintExeField.setEnabled(enabled);
ScssLintConfigFilePathLabel.setEnabled(enabled);
scssLintExeLabel.setEnabled(enabled);
treatAllIssuesCheckBox.setEnabled(enabled);
}
private void validate() {
Validator validator = new Validator();
if (!ValidationUtils.validatePath(project, scssLintExeField.getChildComponent().getText(), false)) {
validator.add(scssLintExeField.getChildComponent().getTextEditor(), "Path to Scss Lint exe is invalid {{LINK}}", FIX_IT);
}
if (!ValidationUtils.validatePath(project, scssLintConfigFile.getChildComponent().getText(), true)) {
validator.add(scssLintConfigFile.getChildComponent().getTextEditor(), "Path to Scss Lint config is invalid {{LINK}}", FIX_IT); //Please correct path to
}
if (validator.hasErrors()) {
versionLabel.setText("n.a.");
} else {
updateVersion();
}
packagesNotificationPanel.processErrors(validator);
}
private ScssLintRunner.ScssLintSettings settings;
private void updateVersion() {
String scssExe = scssLintExeField.getChildComponent().getText();
if (settings != null &&
settings.scssLintExe.equals(scssExe) &&
settings.cwd.equals(project.getBasePath())) {
return;
}
if (StringUtils.isEmpty(scssExe)) {
return;
}
getVersion(scssExe, project.getBasePath());
}
private void getVersion(String scssExe, String cwd) {
if (StringUtils.isEmpty(scssExe)) {
return;
}
settings = new ScssLintRunner.ScssLintSettings();
settings.scssLintExe = scssExe;
settings.cwd = cwd;
try {
versionLabel.setText(ScssLintRunner.runVersion(settings));
} catch (Exception e) {
versionLabel.setText("error");
e.printStackTrace();
}
}
private void configESLintBinField() {
TextFieldWithHistory textFieldWithHistory = scssLintExeField.getChildComponent();
textFieldWithHistory.setHistorySize(-1);
textFieldWithHistory.setMinimumAndPreferredWidth(0);
SwingHelper.addHistoryOnExpansion(textFieldWithHistory, new NotNullProducer<List<String>>() {
@NotNull
public List<String> produce() {
// File projectRoot = new File(project.getBaseDir().getPath());
List<File> newFiles = ScssLintFinder.findAllScssLintExe(); //searchForESLintBin(projectRoot);
return FileUtils.toAbsolutePath(newFiles);
}
});
SwingHelper.installFileCompletionAndBrowseDialog(project, scssLintExeField, "Select SCSS Lint Exe", FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor());
}
private void configScssLintConfigField() {
TextFieldWithHistory textFieldWithHistory = scssLintConfigFile.getChildComponent();
textFieldWithHistory.setHistorySize(-1);
textFieldWithHistory.setMinimumAndPreferredWidth(0);
SwingHelper.addHistoryOnExpansion(textFieldWithHistory, new NotNullProducer<List<String>>() {
@NotNull
public List<String> produce() {
File projectRoot = new File(project.getBaseDir().getPath());
return ScssLintFinder.searchForLintConfigFiles(projectRoot);
}
});
SwingHelper.installFileCompletionAndBrowseDialog(project, scssLintConfigFile, "Select SCSS Lint Config", FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor());
}
@Nls
@Override
public String getDisplayName() {
return "SCSS Lint";
}
@Nullable
@Override
public String getHelpTopic() {
return null;
}
@Nullable
@Override
public JComponent createComponent() {
loadSettings();
getVersion(scssLintExeField.getChildComponent().getText(), project.getBasePath());
addListeners();
return panel;
}
@Override
public boolean isModified() {
return pluginEnabledCheckbox.isSelected() != getSettings().pluginEnabled
|| !scssLintExeField.getChildComponent().getText().equals(getSettings().scssLintExecutable)
|| treatAllIssuesCheckBox.isSelected() != getSettings().treatAllIssuesAsWarnings
|| !getLintConfigFile().equals(getSettings().scssLintConfigFile);
}
private String getLintConfigFile() {
return useSpecificConfigRadioButton.isSelected() ? scssLintConfigFile.getChildComponent().getText() : "";
}
@Override
public void apply() throws ConfigurationException {
saveSettings();
PsiManager.getInstance(project).dropResolveCaches();
}
private void saveSettings() {
Settings settings = getSettings();
settings.pluginEnabled = pluginEnabledCheckbox.isSelected();
settings.scssLintExecutable = scssLintExeField.getChildComponent().getText();
settings.scssLintConfigFile = getLintConfigFile();
settings.treatAllIssuesAsWarnings = treatAllIssuesCheckBox.isSelected();
project.getComponent(ScssLintProjectComponent.class).validateSettings();
DaemonCodeAnalyzer.getInstance(project).restart();
}
private void loadSettings() {
Settings settings = getSettings();
pluginEnabledCheckbox.setSelected(settings.pluginEnabled);
scssLintExeField.getChildComponent().setText(settings.scssLintExecutable);
scssLintConfigFile.getChildComponent().setText(settings.scssLintConfigFile);
boolean hasConfig = StringUtils.isNotEmpty(settings.scssLintConfigFile);
searchForConfigInRadioButton.setSelected(!hasConfig);
useSpecificConfigRadioButton.setSelected(hasConfig);
scssLintConfigFile.setEnabled(hasConfig);
treatAllIssuesCheckBox.setSelected(settings.treatAllIssuesAsWarnings);
setEnabledState(settings.pluginEnabled);
}
@Override
public void reset() {
loadSettings();
}
@Override
public void disposeUIResources() {
}
protected Settings getSettings() {
return Settings.getInstance(project);
}
private void createUIComponents() {
// TODO: place custom component creation code here
usageLink = SwingHelper.createWebHyperlink(HOW_TO_USE_SCSS_LINT, HOW_TO_USE_LINK);
}
public void showSettings() {
String dimensionKey = ShowSettingsUtilImpl.createDimensionKey(this);
SingleConfigurableEditor singleConfigurableEditor = new SingleConfigurableEditor(project, this, dimensionKey, false);
singleConfigurableEditor.show();
}
}