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())); } }