package com.github.masahirosuzuka.PhoneGapIntelliJPlugin.runner.ui;
import com.github.masahirosuzuka.PhoneGapIntelliJPlugin.PhoneGapBundle;
import com.github.masahirosuzuka.PhoneGapIntelliJPlugin.PhoneGapUtil;
import com.github.masahirosuzuka.PhoneGapIntelliJPlugin.commandLine.PhoneGapTargets;
import com.github.masahirosuzuka.PhoneGapIntelliJPlugin.runner.PhoneGapRunConfiguration;
import com.github.masahirosuzuka.PhoneGapIntelliJPlugin.settings.PhoneGapSettings;
import com.intellij.execution.ExecutionBundle;
import com.intellij.execution.configuration.EnvironmentVariablesTextFieldWithBrowseButton;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.TextFieldWithHistoryWithBrowseButton;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.FormBuilder;
import com.intellij.util.ui.ReloadableComboBoxPanel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static com.github.masahirosuzuka.PhoneGapIntelliJPlugin.commandLine.PhoneGapCommandLine.*;
public class PhoneGapRunConfigurationEditor extends SettingsEditor<PhoneGapRunConfiguration> {
public static final ArrayList<String> COMMANDS_LIST =
ContainerUtil.newArrayList(COMMAND_EMULATE, COMMAND_RUN, COMMAND_PREPARE, COMMAND_SERVE);
public static final ArrayList<String> COMMANDS_PHONEGAP_LIST =
ContainerUtil.newArrayList(COMMAND_EMULATE, COMMAND_RUN, COMMAND_PREPARE, COMMAND_SERVE, COMMAND_REMOTE_BUILD, COMMAND_REMOTE_RUN);
public static final String PLATFORM_ANDROID = "android";
public static final String PLATFORM_IOS = "ios";
public static final String PLATFORM_AMAZON_FIREOS = "amazon-fireos";
public static final String PLATFORM_BLACKBERRY_10 = "blackberry10";
public static final String PLATFORM_UBUNTU = "ubuntu";
public static final String PLATFORM_WP_8 = "wp8";
public static final String PLATFORM_WINDOWS_8 = "windows8";
public static final String PLATFORM_WINDOWS = "windows";
public static final String PLATFORM_FIREFOXOS = "firefoxos";
public static final String PLATFORM_BROWSER = "browser";
private TextFieldWithHistoryWithBrowseButton myExecutablePathField;
private TextFieldWithHistoryWithBrowseButton myWorkDirField;
private ComboBoxWithMoreOption myPlatformField;
private ComboBox myCommand;
private final Project myProject;
private JBCheckBox myHasTarget;
private PhoneGapTargetsPanel myTarget;
private JBTextField myExtraArgsTextField;
private EnvironmentVariablesTextFieldWithBrowseButton myEnvComponent;
public PhoneGapRunConfigurationEditor(Project project) {
myProject = project;
}
@Override
protected void resetEditorFrom(@NotNull PhoneGapRunConfiguration s) {
String executable = s.getExecutable();
PhoneGapUtil.setFieldWithHistoryWithBrowseButtonPath(myExecutablePathField,
!StringUtil.isEmpty(executable)
? executable
: PhoneGapSettings.getInstance().getExecutablePath());
String item = s.getPlatform();
if (item != null) {
//call to lower for back compatibility (old settings store 'iOS' and 'Android')
myPlatformField.setSelectedWithExtend(StringUtil.toLowerCase(item));
}
String command = s.getCommand();
if (command != null) {
myCommand.setSelectedItem(command);
}
String workDir = s.getWorkDir();
PhoneGapUtil.setFieldWithHistoryWithBrowseButtonPath(myWorkDirField,
!StringUtil.isEmpty(workDir)
? workDir
: PhoneGapSettings.getInstance().getWorkingDirectory(myProject));
boolean hasTarget = s.hasTarget();
myHasTarget.setSelected(hasTarget);
myExtraArgsTextField.setText(s.getExtraArgs());
myEnvComponent.setEnvs(s.getEnvs());
myEnvComponent.setPassParentEnvs(s.isPassParent());
PhoneGapUtil.setTextFieldWithHistory(myTarget.getTargetsField(), s.getTarget());
fillTargetValuesAndSetVisible(false);
}
private void fillTargetValuesAndSetVisible() {
fillTargetValuesAndSetVisible(true);
}
private void fillTargetValuesAndSetVisible(boolean resetField) {
setTargetFieldsEnable();
if (resetField) {
myTarget.getTargetsField().setHistory(ContainerUtil.emptyList());
myTarget.getTargetsField().setText("");
}
myTarget.reloadValuesInBackground();
}
private String getPlatformAsCodeFromField() {
return (String)myPlatformField.getSelectedItem();
}
@Override
protected void applyEditorTo(@NotNull PhoneGapRunConfiguration persistentSettings) throws ConfigurationException {
persistentSettings.setExecutable(myExecutablePathField.getText());
String item = (String)myPlatformField.getSelectedItem();
persistentSettings.setPlatform(item);
persistentSettings.setCommand((String)myCommand.getSelectedItem());
persistentSettings.setWorkDir(myWorkDirField.getText());
persistentSettings.setTarget(myTarget.getSelectedValue());
persistentSettings.setHasTarget(myHasTarget.isSelected());
persistentSettings.setExtraArgs(myExtraArgsTextField.getText());
persistentSettings.setEnvs(myEnvComponent.getEnvs());
persistentSettings.setPassParent(myEnvComponent.isPassParentEnvs());
}
@NotNull
@Override
protected JComponent createEditor() {
myExecutablePathField = PhoneGapUtil.createPhoneGapExecutableTextField(myProject);
myWorkDirField = PhoneGapUtil.createPhoneGapWorkingDirectoryField(myProject);
myPlatformField = new ComboBoxWithMoreOption(getDefaultPlatforms(), getNonDefaultPlatforms());
myCommand = new ComboBox();
myEnvComponent = new EnvironmentVariablesTextFieldWithBrowseButton();
myEnvComponent.setPassParentEnvs(true);
myHasTarget = new JBCheckBox("Specify target");
myTarget = new PhoneGapTargetsPanel();
myExtraArgsTextField = new JBTextField(15);
myCommand.setMinimumAndPreferredWidth(200);
myPlatformField.setMinimumAndPreferredWidth(200);
myTarget.getTargetsField().setMinimumAndPreferredWidth(myPlatformField.getPreferredSize().width);
myTarget.setDataProvider(new ReloadableComboBoxPanel.DataProvider<String>() {
@NotNull
@Override
public Set<String> getCachedValues() {
return ContainerUtil.newHashOrEmptySet(null);
}
@Override
public void updateValuesAsynchronously() {
if (!myTarget.isEnabled()) {
processEmpty();
return;
}
final String platform = getPlatformAsCodeFromField();
final String command = (String)myCommand.getSelectedItem();
final PhoneGapTargets targetsProvider = PhoneGapTargets.createTargetsList(myProject, platform);
if (targetsProvider == null) {
processEmpty();
return;
}
ApplicationManager.getApplication().executeOnPooledThread(() -> {
final String currentText = myTarget.getTargetsField().getText();
final Set<String> targets = ContainerUtil.newLinkedHashSet(PhoneGapTargets.listTargets(targetsProvider, command));
if (!StringUtil.isEmpty(currentText) && !targets.contains(currentText)) {
targets.add(currentText);
}
UIUtil.invokeLaterIfNeeded(() -> myTarget.onUpdateValues(targets));
});
}
private void processEmpty() {
myTarget.onUpdateValues(ContainerUtil.newHashOrEmptySet(null));
}
});
setListenerForPlatforms();
setListenerForCommand();
setListenerForHasTarget();
setListenerForExecutablePath();
setCommandList();
return FormBuilder.createFormBuilder()
.addLabeledComponent(PhoneGapBundle.message("phonegap.conf.executable.name"), myExecutablePathField)
.addLabeledComponent(PhoneGapBundle.message("phonegap.conf.work.dir.name"), myWorkDirField)
.addLabeledComponent(ExecutionBundle.message("environment.variables.component.title"), myEnvComponent)
.addLabeledComponent("Command:", myCommand)
.addLabeledComponent("Platform:", myPlatformField)
.addLabeledComponent(PhoneGapBundle.message("phonegap.conf.extra.args.name"), myExtraArgsTextField)
.addLabeledComponent(myHasTarget, myTarget.getMainPanel())
.getPanel();
}
private void setListenerForPlatforms() {
myPlatformField.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
fillTargetValuesAndSetVisible();
}
});
}
private void setListenerForHasTarget() {
myHasTarget.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
fillTargetValuesAndSetVisible();
}
});
}
private void setListenerForCommand() {
myCommand.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
fillTargetValuesAndSetVisible();
}
}
});
}
private void setListenerForExecutablePath() {
final Ref<String> prevExecutablePathRef = Ref.create(StringUtil.notNullize(myExecutablePathField.getText()));
final JTextField textEditor = myExecutablePathField.getChildComponent().getTextEditor();
textEditor.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
String executablePath = StringUtil.notNullize(textEditor.getText());
if (StringUtil.isEmpty(executablePath)) return;
String prevExecutablePath = prevExecutablePathRef.get();
if (!prevExecutablePath.equals(executablePath)) {
setCommandList();
prevExecutablePathRef.set(executablePath);
}
}
});
}
@SuppressWarnings("unchecked")
private static void addItems(ComboBox box, List<String> list) {
for (String s : list) {
box.addItem(s);
}
box.setSelectedIndex(0);
}
private void setCommandList() {
String selectedItem = (String)myCommand.getSelectedItem();
if (isPhoneGap()) {
replaceCommandList(selectedItem, COMMANDS_PHONEGAP_LIST);
}
else {
replaceCommandList(selectedItem, COMMANDS_LIST);
}
}
private void replaceCommandList(String selectedItem, List<String> commandList) {
if (myCommand.getItemCount() == commandList.size()) return;
myCommand.removeAllItems();
addItems(myCommand, commandList);
if (commandList.contains(selectedItem)) {
myCommand.setSelectedItem(selectedItem);
}
}
private static Set<String> getDefaultPlatforms() {
LinkedHashSet<String> set = ContainerUtil.newLinkedHashSet();
set.add(PLATFORM_ANDROID);
set.add(PLATFORM_IOS);
set.add(PLATFORM_BROWSER);
return set;
}
private static Set<String> getNonDefaultPlatforms() {
LinkedHashSet<String> set = ContainerUtil.newLinkedHashSet();
set.add(PLATFORM_AMAZON_FIREOS);
set.add(PLATFORM_FIREFOXOS);
set.add(PLATFORM_BLACKBERRY_10);
set.add(PLATFORM_UBUNTU);
set.add(PLATFORM_WP_8);
set.add(PLATFORM_WINDOWS);
set.add(PLATFORM_WINDOWS_8);
return set;
}
private void setTargetFieldsEnable() {
boolean isNotServe = !COMMAND_SERVE.equals(myCommand.getSelectedItem());
myHasTarget.setEnabled(isNotServe);
myTarget.setEnabled(isNotServe && myHasTarget.isSelected());
}
private boolean isPhoneGap() {
return Boolean.TRUE.equals(isPhoneGapExecutableByPath(myExecutablePathField.getText()));
}
}