| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.jetbrains.python; |
| |
| import com.intellij.application.options.ModulesComboBox; |
| import com.intellij.execution.configuration.EnvironmentVariablesComponent; |
| import com.intellij.execution.util.PathMappingsComponent; |
| import com.intellij.ide.util.PropertiesComponent; |
| import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.module.ModuleManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.projectRoots.SdkModel; |
| import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer; |
| import com.intellij.openapi.roots.ModuleRootManager; |
| import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; |
| import com.intellij.openapi.ui.ComboBox; |
| import com.intellij.openapi.ui.TextFieldWithBrowseButton; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.ui.CollectionComboBoxModel; |
| import com.intellij.ui.HideableDecorator; |
| import com.intellij.ui.RawCommandLineEditor; |
| import com.intellij.ui.components.JBCheckBox; |
| import com.intellij.ui.components.JBLabel; |
| import com.intellij.util.PathMappingSettings; |
| import com.jetbrains.python.configuration.PyConfigurableInterpreterList; |
| import com.jetbrains.python.configuration.PyConfigureInterpretersLinkPanel; |
| import com.jetbrains.python.run.AbstractPyCommonOptionsForm; |
| import com.jetbrains.python.run.PyCommonOptionsFormData; |
| import com.jetbrains.python.sdk.PySdkUtil; |
| import com.jetbrains.python.sdk.PythonSdkType; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ActionListener; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * @author yole |
| */ |
| public class PyIdeCommonOptionsForm implements AbstractPyCommonOptionsForm { |
| private JPanel myMainPanel; |
| private EnvironmentVariablesComponent myEnvsComponent; |
| private RawCommandLineEditor myInterpreterOptionsTextField; |
| private TextFieldWithBrowseButton myWorkingDirectoryTextField; |
| private JComboBox myInterpreterComboBox; |
| private JBLabel myPythonInterpreterJBLabel; |
| private JLabel myProjectLabel; |
| private ModulesComboBox myModuleCombo; |
| private JPanel myConfigureInterpretersPanel; |
| private String mySelectedSdkHome = null; |
| private PathMappingsComponent myPathMappingsComponent; |
| private JPanel myHideablePanel; |
| private JBCheckBox myAddContentRootsCheckbox; |
| private JBCheckBox myAddSourceRootsCheckbox; |
| |
| private JComponent labelAnchor; |
| private final Project myProject; |
| private List<Sdk> myPythonSdks; |
| private boolean myInterpreterRemote; |
| private final HideableDecorator myDecorator; |
| |
| public PyIdeCommonOptionsForm(PyCommonOptionsFormData data) { |
| myProject = data.getProject(); |
| myWorkingDirectoryTextField.addBrowseFolderListener("Select Working Directory", "", data.getProject(), |
| FileChooserDescriptorFactory.createSingleFolderDescriptor()); |
| |
| myPythonSdks = new ArrayList<Sdk>(PythonSdkType.getAllSdks()); |
| myPythonSdks.add(0, null); |
| |
| myInterpreterComboBox.setModel(new CollectionComboBoxModel(myPythonSdks, null)); |
| |
| final Module[] modules = ModuleManager.getInstance(data.getProject()).getModules(); |
| if (modules.length == 1) { |
| setModule(modules[0]); |
| myProjectLabel.setVisible(false); |
| myModuleCombo.setVisible(false); |
| } |
| else { |
| final List<Module> validModules = data.getValidModules(); |
| Module selection = validModules.size() > 0 ? validModules.get(0) : null; |
| myModuleCombo.setModules(validModules); |
| myModuleCombo.setSelectedModule(selection); |
| myModuleCombo.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| updateDefaultInterpreter(myModuleCombo.getSelectedModule()); |
| } |
| }); |
| updateDefaultInterpreter(myModuleCombo.getSelectedModule()); |
| } |
| |
| setAnchor(myEnvsComponent.getLabel()); |
| myPathMappingsComponent.setAnchor(myEnvsComponent.getLabel()); |
| |
| if (data.showConfigureInterpretersLink()) { |
| myConfigureInterpretersPanel.add(new PyConfigureInterpretersLinkPanel(myMainPanel)); |
| } |
| |
| addInterpreterComboBoxActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent event) { |
| updateRemoteInterpreterMode(); |
| } |
| } |
| ); |
| |
| updateRemoteInterpreterMode(); |
| |
| myDecorator = new HideableDecorator(myHideablePanel, "Environment", false) { |
| @Override |
| protected void on() { |
| super.on(); |
| storeState(); |
| } |
| |
| @Override |
| protected void off() { |
| super.off(); |
| storeState(); |
| } |
| private void storeState() { |
| PropertiesComponent.getInstance().setValue(EXPAND_PROPERTY_KEY, String.valueOf(isExpanded())); |
| } |
| }; |
| myDecorator.setOn(PropertiesComponent.getInstance().getBoolean(EXPAND_PROPERTY_KEY, true)); |
| myDecorator.setContentComponent(myMainPanel); |
| } |
| |
| @Override |
| public JComponent getMainPanel() { |
| return myHideablePanel; |
| } |
| |
| @Override |
| public void subscribe() { |
| PyConfigurableInterpreterList myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject); |
| ProjectSdksModel myProjectSdksModel = myInterpreterList.getModel(); |
| myProjectSdksModel.addListener(new MyListener(this, myInterpreterList)); |
| updateSdkList(true, myInterpreterList); |
| } |
| |
| @Override |
| public JComponent getAnchor() { |
| return labelAnchor; |
| } |
| |
| @Override |
| public void setAnchor(JComponent anchor) { |
| labelAnchor = anchor; |
| myEnvsComponent.setAnchor(anchor); |
| myPythonInterpreterJBLabel.setAnchor(anchor); |
| } |
| |
| public String getInterpreterOptions() { |
| return myInterpreterOptionsTextField.getText().trim(); |
| } |
| |
| public void setInterpreterOptions(String interpreterOptions) { |
| myInterpreterOptionsTextField.setText(interpreterOptions); |
| } |
| |
| public String getWorkingDirectory() { |
| return FileUtil.toSystemIndependentName(myWorkingDirectoryTextField.getText().trim()); |
| } |
| |
| public void setWorkingDirectory(String workingDirectory) { |
| myWorkingDirectoryTextField.setText(workingDirectory == null ? "" : FileUtil.toSystemDependentName(workingDirectory)); |
| } |
| |
| @Override |
| public String getSdkHome() { |
| final Sdk selectedSdk = (Sdk)myInterpreterComboBox.getSelectedItem(); |
| return selectedSdk == null ? null : selectedSdk.getHomePath(); |
| } |
| |
| @Override |
| public void setSdkHome(String sdkHome) { |
| mySelectedSdkHome = sdkHome; |
| } |
| |
| @Nullable |
| @Override |
| public Module getModule() { |
| final Module selectedItem = myModuleCombo.getSelectedModule(); |
| if (selectedItem != null) { |
| return selectedItem; |
| } |
| final Module[] modules = ModuleManager.getInstance(myProject).getModules(); |
| if (modules.length == 1) { |
| return modules[0]; |
| } |
| return null; |
| } |
| |
| @Override |
| public void setModule(Module module) { |
| myModuleCombo.setSelectedModule(module); |
| updateDefaultInterpreter(module); |
| } |
| |
| private void updateDefaultInterpreter(Module module) { |
| final Sdk sdk = module == null ? null : ModuleRootManager.getInstance(module).getSdk(); |
| String projectSdkName = sdk == null ? "none" : sdk.getName(); |
| myInterpreterComboBox.setRenderer(new SdkListCellRenderer("Project Default (" + projectSdkName + ")")); |
| } |
| |
| public void updateSdkList(boolean preserveSelection, PyConfigurableInterpreterList myInterpreterList) { |
| myPythonSdks = myInterpreterList.getAllPythonSdks(myProject); |
| Sdk selection = preserveSelection ? (Sdk)myInterpreterComboBox.getSelectedItem() : null; |
| if (!myPythonSdks.contains(selection)) { |
| selection = null; |
| } |
| myPythonSdks.add(0, null); |
| myInterpreterComboBox.setModel(new CollectionComboBoxModel(myPythonSdks, selection)); |
| } |
| |
| @Override |
| public boolean isUseModuleSdk() { |
| return myInterpreterComboBox.getSelectedItem() == null; |
| } |
| |
| @Override |
| public void setUseModuleSdk(boolean useModuleSdk) { |
| myInterpreterComboBox.setSelectedItem(useModuleSdk ? null : PythonSdkType.findSdkByPath(myPythonSdks, mySelectedSdkHome)); |
| } |
| |
| public boolean isPassParentEnvs() { |
| return myEnvsComponent.isPassParentEnvs(); |
| } |
| |
| public void setPassParentEnvs(boolean passParentEnvs) { |
| myEnvsComponent.setPassParentEnvs(passParentEnvs); |
| } |
| |
| public Map<String, String> getEnvs() { |
| return myEnvsComponent.getEnvs(); |
| } |
| |
| public void setEnvs(Map<String, String> envs) { |
| myEnvsComponent.setEnvs(envs); |
| } |
| |
| @Override |
| @Nullable |
| public PathMappingSettings getMappingSettings() { |
| if (myInterpreterRemote) { |
| return myPathMappingsComponent.getMappingSettings(); |
| } |
| else { |
| return new PathMappingSettings(); |
| } |
| } |
| |
| @Override |
| public void setMappingSettings(@Nullable PathMappingSettings mappingSettings) { |
| myPathMappingsComponent.setMappingSettings(mappingSettings); |
| } |
| |
| @Override |
| public boolean addContentRoots() { |
| return myAddContentRootsCheckbox.isSelected(); |
| } |
| |
| @Override |
| public boolean addSourceRoots() { |
| return myAddSourceRootsCheckbox.isSelected(); |
| } |
| |
| @Override |
| public void addContentRoots(boolean add) { |
| myAddContentRootsCheckbox.setSelected(add); |
| } |
| |
| @Override |
| public void addSourceRoots(boolean add) { |
| myAddSourceRootsCheckbox.setSelected(add); |
| } |
| |
| private void createUIComponents() { |
| myInterpreterComboBox = new ComboBox(100); |
| } |
| |
| private void setRemoteInterpreterMode(boolean isInterpreterRemote) { |
| myInterpreterRemote = isInterpreterRemote; |
| myPathMappingsComponent.setVisible(isInterpreterRemote); |
| } |
| |
| private void updateRemoteInterpreterMode() { |
| setRemoteInterpreterMode(PySdkUtil.isRemote(getSdkSelected())); |
| } |
| |
| @Nullable |
| private Sdk getSdkSelected() { |
| String sdkHome = getSdkHome(); |
| if (StringUtil.isEmptyOrSpaces(sdkHome)) { |
| final Sdk projectJdk = PythonSdkType.findPythonSdk(getModule()); |
| if (projectJdk != null) { |
| sdkHome = projectJdk.getHomePath(); |
| } |
| } |
| |
| return PythonSdkType.findSdkByPath(sdkHome); |
| } |
| |
| @Override |
| public void addInterpreterComboBoxActionListener(ActionListener listener) { |
| myInterpreterComboBox.addActionListener(listener); |
| } |
| |
| @Override |
| public void removeInterpreterComboBoxActionListener(ActionListener listener) { |
| myInterpreterComboBox.removeActionListener(listener); |
| } |
| |
| private static class MyListener implements SdkModel.Listener { |
| private final PyIdeCommonOptionsForm myForm; |
| private PyConfigurableInterpreterList myInterpreterList; |
| |
| public MyListener(PyIdeCommonOptionsForm form, PyConfigurableInterpreterList interpreterList) { |
| myForm = form; |
| myInterpreterList = interpreterList; |
| } |
| |
| |
| private void update() { |
| myForm.updateSdkList(true, myInterpreterList); |
| } |
| |
| @Override |
| public void sdkAdded(Sdk sdk) { |
| update(); |
| } |
| |
| @Override |
| public void beforeSdkRemove(Sdk sdk) { |
| update(); |
| } |
| |
| @Override |
| public void sdkChanged(Sdk sdk, String previousName) { |
| update(); |
| } |
| |
| @Override |
| public void sdkHomeSelected(Sdk sdk, String newSdkHome) { |
| } |
| } |
| } |