Merge branch 'master' into traff/zip_helpers
[idea/community.git] / python / pluginSrc / com / jetbrains / python / run / PyPluginCommonOptionsForm.java
1 /*
2  * Copyright 2000-2015 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.jetbrains.python.run;
17
18 import com.intellij.application.options.ModulesComboBox;
19 import com.intellij.execution.configuration.EnvironmentVariablesComponent;
20 import com.intellij.execution.util.PathMappingsComponent;
21 import com.intellij.ide.util.PropertiesComponent;
22 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.module.ModuleManager;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.projectRoots.Sdk;
27 import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
28 import com.intellij.openapi.roots.ModuleRootManager;
29 import com.intellij.openapi.roots.ProjectRootManager;
30 import com.intellij.openapi.roots.ui.configuration.ModulesAlphaComparator;
31 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
32 import com.intellij.openapi.util.io.FileUtil;
33 import com.intellij.ui.CollectionComboBoxModel;
34 import com.intellij.ui.HideableDecorator;
35 import com.intellij.ui.RawCommandLineEditor;
36 import com.intellij.ui.components.JBCheckBox;
37 import com.intellij.ui.components.JBLabel;
38 import com.intellij.util.PathMappingSettings;
39 import com.jetbrains.python.sdk.PreferredSdkComparator;
40 import com.jetbrains.python.sdk.PySdkUtil;
41 import com.jetbrains.python.sdk.PythonSdkType;
42 import org.jetbrains.annotations.Nullable;
43
44 import javax.swing.*;
45 import java.awt.event.ActionEvent;
46 import java.awt.event.ActionListener;
47 import java.util.ArrayList;
48 import java.util.Collections;
49 import java.util.List;
50 import java.util.Map;
51
52 /**
53  * @author yole
54  */
55 public class PyPluginCommonOptionsForm implements AbstractPyCommonOptionsForm {
56   private final Project myProject;
57   private TextFieldWithBrowseButton myWorkingDirectoryTextField;
58   private EnvironmentVariablesComponent myEnvsComponent;
59   private RawCommandLineEditor myInterpreterOptionsTextField;
60   private JComboBox myInterpreterComboBox;
61   private JRadioButton myUseModuleSdkRadioButton;
62   private ModulesComboBox myModuleComboBox;
63   private JPanel myMainPanel;
64   private JRadioButton myUseSpecifiedSdkRadioButton;
65   private JBLabel myPythonInterpreterJBLabel;
66   private JBLabel myInterpreterOptionsJBLabel;
67   private JBLabel myWorkingDirectoryJBLabel;
68   private JPanel myHideablePanel;
69   private PathMappingsComponent myPathMappingsComponent;
70   private JBCheckBox myAddContentRootsCheckbox;
71   private JBCheckBox myAddSourceRootsCheckbox;
72   private JComponent labelAnchor;
73   private final HideableDecorator myDecorator;
74
75   public PyPluginCommonOptionsForm(PyCommonOptionsFormData data) {
76     // setting modules
77     myProject = data.getProject();
78     final List<Module> validModules = data.getValidModules();
79     Collections.sort(validModules, new ModulesAlphaComparator());
80     Module selection = validModules.size() > 0 ? validModules.get(0) : null;
81     myModuleComboBox.setModules(validModules);
82     myModuleComboBox.setSelectedModule(selection);
83
84     myInterpreterComboBox.setRenderer(new SdkListCellRenderer("<Project Default>"));
85     myWorkingDirectoryTextField.addBrowseFolderListener("Select Working Directory", "", data.getProject(),
86                                                   FileChooserDescriptorFactory.createSingleFolderDescriptor());
87
88     ActionListener listener = new ActionListener() {
89       public void actionPerformed(ActionEvent e) {
90         updateControls();
91       }
92     };
93     myUseSpecifiedSdkRadioButton.addActionListener(listener);
94     myUseModuleSdkRadioButton.addActionListener(listener);
95     myInterpreterComboBox.addActionListener(listener);
96     myModuleComboBox.addActionListener(listener);
97
98     setAnchor(myEnvsComponent.getLabel());
99
100
101     myDecorator = new HideableDecorator(myHideablePanel, "Environment", false) {
102       @Override
103       protected void on() {
104         super.on();
105         storeState();
106       }
107
108       @Override
109       protected void off() {
110         super.off();
111         storeState();
112       }
113       private void storeState() {
114         PropertiesComponent.getInstance().setValue(EXPAND_PROPERTY_KEY, String.valueOf(isExpanded()), "true");
115       }
116     };
117     myDecorator.setOn(PropertiesComponent.getInstance().getBoolean(EXPAND_PROPERTY_KEY, true));
118     myDecorator.setContentComponent(myMainPanel);
119     myPathMappingsComponent.setAnchor(myEnvsComponent.getLabel());
120     updateControls();
121   }
122
123   private void updateControls() {
124     myModuleComboBox.setEnabled(myUseModuleSdkRadioButton.isSelected());
125     myInterpreterComboBox.setEnabled(myUseSpecifiedSdkRadioButton.isSelected());
126     myPathMappingsComponent.setVisible(PySdkUtil.isRemote(getSelectedSdk()));
127   }
128
129   public JPanel getMainPanel() {
130     return myHideablePanel;
131   }
132
133   @Override
134   public void subscribe() {
135   }
136
137   @Override
138   public void addInterpreterComboBoxActionListener(ActionListener listener) {
139     myInterpreterComboBox.addActionListener(listener);
140   }
141
142   @Override
143   public void removeInterpreterComboBoxActionListener(ActionListener listener) {
144     myInterpreterComboBox.removeActionListener(listener);
145   }
146
147   public String getInterpreterOptions() {
148     return myInterpreterOptionsTextField.getText().trim();
149   }
150
151   public void setInterpreterOptions(String interpreterOptions) {
152     myInterpreterOptionsTextField.setText(interpreterOptions);
153   }
154
155   public String getWorkingDirectory() {
156     return FileUtil.toSystemIndependentName(myWorkingDirectoryTextField.getText().trim());
157   }
158
159   public void setWorkingDirectory(String workingDirectory) {
160     myWorkingDirectoryTextField.setText(workingDirectory == null ? "" : FileUtil.toSystemDependentName(workingDirectory));
161   }
162
163   @Nullable
164   public String getSdkHome() {
165     Sdk selectedSdk = (Sdk)myInterpreterComboBox.getSelectedItem();
166     return selectedSdk == null ? null : selectedSdk.getHomePath();
167   }
168
169   public void setSdkHome(String sdkHome) {
170     List<Sdk> sdkList = new ArrayList<Sdk>();
171     sdkList.add(null);
172     final List<Sdk> allSdks = PythonSdkType.getAllSdks();
173     Collections.sort(allSdks, new PreferredSdkComparator());
174     Sdk selection = null;
175     for (Sdk sdk : allSdks) {
176       String homePath = sdk.getHomePath();
177       if (homePath != null && sdkHome != null && FileUtil.pathsEqual(homePath, sdkHome)) selection = sdk;
178       sdkList.add(sdk);
179     }
180
181     myInterpreterComboBox.setModel(new CollectionComboBoxModel(sdkList, selection));
182   }
183
184   public Module getModule() {
185     return myModuleComboBox.getSelectedModule();
186   }
187
188   @Override
189   public String getModuleName() {
190     Module module = getModule();
191     return module != null? module.getName() : null;
192   }
193
194   public void setModule(Module module) {
195     myModuleComboBox.setSelectedModule(module);
196   }
197
198   public boolean isUseModuleSdk() {
199     return myUseModuleSdkRadioButton.isSelected();
200   }
201
202   public void setUseModuleSdk(boolean useModuleSdk) {
203     if (useModuleSdk) {
204       myUseModuleSdkRadioButton.setSelected(true);
205     }
206     else {
207       myUseSpecifiedSdkRadioButton.setSelected(true);
208     }
209     updateControls();
210   }
211
212   public boolean isPassParentEnvs() {
213     return myEnvsComponent.isPassParentEnvs();
214   }
215
216   public void setPassParentEnvs(boolean passParentEnvs) {
217     myEnvsComponent.setPassParentEnvs(passParentEnvs);
218   }
219
220   public Map<String, String> getEnvs() {
221     return myEnvsComponent.getEnvs();
222   }
223
224   public void setEnvs(Map<String, String> envs) {
225     myEnvsComponent.setEnvs(envs);
226   }
227
228   @Override
229   public PathMappingSettings getMappingSettings() {
230     return myPathMappingsComponent.getMappingSettings();
231   }
232
233   @Override
234   public void setMappingSettings(@Nullable PathMappingSettings mappingSettings) {
235     myPathMappingsComponent.setMappingSettings(mappingSettings);
236   }
237
238   private Sdk getSelectedSdk() {
239     if (isUseModuleSdk()) {
240       Module module = getModule();
241       return module == null ? null : ModuleRootManager.getInstance(module).getSdk();
242     }
243     Sdk sdk = (Sdk)myInterpreterComboBox.getSelectedItem();
244     if (sdk == null) {
245       return ProjectRootManager.getInstance(myProject).getProjectSdk();
246     }
247     return sdk;
248   }
249
250   @Override
251   public JComponent getAnchor() {
252     return labelAnchor;
253   }
254
255   @Override
256   public void setAnchor(JComponent anchor) {
257     labelAnchor = anchor;
258     myPythonInterpreterJBLabel.setAnchor(anchor);
259     myInterpreterOptionsJBLabel.setAnchor(anchor);
260     myWorkingDirectoryJBLabel.setAnchor(anchor);
261     myEnvsComponent.setAnchor(anchor);
262   }
263
264   @Override
265   public boolean shouldAddContentRoots() {
266     return myAddContentRootsCheckbox.isSelected();
267   }
268
269   @Override
270   public boolean shouldAddSourceRoots() {
271     return myAddSourceRootsCheckbox.isSelected();
272   }
273
274   @Override
275   public void setAddContentRoots(boolean flag) {
276     myAddContentRootsCheckbox.setSelected(flag);
277   }
278
279   @Override
280   public void setAddSourceRoots(boolean flag) {
281     myAddSourceRootsCheckbox.setSelected(flag);
282   }
283 }