blob: 79c35527e67389bd7d5609bdfc89a9027d89596e [file] [log] [blame]
/*
* 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) {
}
}
}