diff options
Diffstat (limited to 'python/ide/src')
10 files changed, 198 insertions, 512 deletions
diff --git a/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java b/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java index 3b590371e610..79c35527e673 100644 --- a/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java +++ b/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java @@ -15,6 +15,7 @@ */ 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; @@ -26,7 +27,6 @@ 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.application.options.ModulesComboBox; import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.TextFieldWithBrowseButton; diff --git a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java index bcbebc3b2639..ca00208c3c88 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java +++ b/python/ide/src/com/jetbrains/python/configuration/PyContentEntriesModuleConfigurable.java @@ -1,60 +1,29 @@ package com.jetbrains.python.configuration; import com.intellij.facet.impl.DefaultFacetsProvider; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.impl.ModuleConfigurationStateImpl; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.ContentFolder; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.impl.ContentEntryImpl; -import com.intellij.openapi.roots.impl.ContentFolderBaseImpl; -import com.intellij.openapi.roots.ui.configuration.*; -import com.intellij.openapi.roots.ui.configuration.actions.ContentEntryEditingAction; -import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider; +import com.intellij.openapi.roots.ui.configuration.FacetsProvider; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vfs.VfsUtilCore; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.pointers.VirtualFilePointer; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener; -import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; -import com.intellij.ui.JBColor; -import com.intellij.util.EventDispatcher; -import com.intellij.util.containers.MultiMap; -import com.jetbrains.python.templateLanguages.TemplatesService; -import icons.PythonIcons; +import com.jetbrains.python.module.PyContentEntriesEditor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.model.java.JavaSourceRootType; -import org.jetbrains.jps.model.module.JpsModuleSourceRootType; import javax.swing.*; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.tree.TreeCellRenderer; import java.awt.*; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.util.ArrayList; -import java.util.List; public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.Parent.Abstract { - private static final Color TEMPLATES_COLOR = JBColor.MAGENTA; - private final Module myModule; private final JPanel myTopPanel = new JPanel(new BorderLayout()); protected ModifiableRootModel myModifiableModel; - protected MyCommonContentEntriesEditor myEditor; + protected PyContentEntriesEditor myEditor; public PyContentEntriesModuleConfigurable(final Module module) { myModule = module; @@ -108,8 +77,8 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P myTopPanel.add(component, BorderLayout.CENTER); } - protected MyCommonContentEntriesEditor createEditor(@NotNull Module module, @NotNull ModuleConfigurationStateImpl state) { - return new MyCommonContentEntriesEditor(module, state, JavaSourceRootType.SOURCE); + protected PyContentEntriesEditor createEditor(@NotNull Module module, @NotNull ModuleConfigurationStateImpl state) { + return new PyContentEntriesEditor(module, state, JavaSourceRootType.SOURCE); } @Override @@ -171,314 +140,4 @@ public class PyContentEntriesModuleConfigurable extends SearchableConfigurable.P return "python.project.structure"; } - private static class MyContentEntryTreeEditor extends ContentEntryTreeEditor { - - private final ChangeListener myListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - update(); - } - }; - - public MyContentEntryTreeEditor(Project project, List<ModuleSourceRootEditHandler<?>> handlers) { - super(project, handlers); - } - - @Override - public void setContentEntryEditor(ContentEntryEditor newEditor) { - MyCommonContentEntriesEditor.MyContentEntryEditor existingEditor = getContentEntryEditor(); - if (Comparing.equal(existingEditor, newEditor)) { - return; - } - if (existingEditor != null) { - existingEditor.removeListener(myListener); - } - if (newEditor != null) { - ((MyCommonContentEntriesEditor.MyContentEntryEditor)newEditor).addListener(myListener); - } - super.setContentEntryEditor(newEditor); - } - - @Override - public MyCommonContentEntriesEditor.MyContentEntryEditor getContentEntryEditor() { - return (MyCommonContentEntriesEditor.MyContentEntryEditor)super.getContentEntryEditor(); - } - - @Override - protected void createEditingActions() { - super.createEditingActions(); - - ContentEntryEditingAction a = new ContentEntryEditingAction(myTree) { - { - final Presentation templatePresentation = getTemplatePresentation(); - templatePresentation.setText("Templates"); - templatePresentation.setDescription("Template Folders"); - templatePresentation.setIcon(PythonIcons.Python.TemplateRoot); - } - - @Override - public boolean isSelected(AnActionEvent e) { - final VirtualFile[] selectedFiles = getSelectedFiles(); - return selectedFiles.length != 0 && getContentEntryEditor().hasTemplateRoot(selectedFiles[0]); - } - - @Override - public void setSelected(AnActionEvent e, boolean isSelected) { - final VirtualFile[] selectedFiles = getSelectedFiles(); - assert selectedFiles.length != 0; - - for (VirtualFile selectedFile : selectedFiles) { - boolean wasSelected = getContentEntryEditor().hasTemplateRoot(selectedFile); - if (isSelected) { - if (!wasSelected) { - getContentEntryEditor().addTemplateRoot(selectedFile); - } - } - else { - if (wasSelected) { - getContentEntryEditor().removeTemplateRoot(selectedFile); - } - } - } - } - }; - myEditingActionsGroup.add(a); - a.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.ALT_MASK)), myTree); - } - - @Override - protected TreeCellRenderer getContentEntryCellRenderer() { - return new ContentEntryTreeCellRenderer(this, getEditHandlers()) { - @Override - protected Icon updateIcon(final ContentEntry entry, final VirtualFile file, final Icon originalIcon) { - if (getContentEntryEditor().hasTemplateRoot(file)) { - return PythonIcons.Python.TemplateRoot; - } - return super.updateIcon(entry, file, originalIcon); - } - }; - } - } - - protected static class MyCommonContentEntriesEditor extends CommonContentEntriesEditor { - private final MultiMap<ContentEntry, VirtualFilePointer> myTemplateRoots = new MultiMap<ContentEntry, VirtualFilePointer>(); - private final Module myModule; - private Disposable myFilePointersDisposable; - - private final VirtualFilePointerListener DUMMY_LISTENER = new VirtualFilePointerListener() { - @Override - public void beforeValidityChanged(@NotNull VirtualFilePointer[] pointers) { - } - - @Override - public void validityChanged(@NotNull VirtualFilePointer[] pointers) { - } - }; - - public MyCommonContentEntriesEditor(Module module, - ModuleConfigurationStateImpl moduleConfigurationState, - JpsModuleSourceRootType<?>... rootTypes) { - super(module.getName(), moduleConfigurationState, rootTypes); - myModule = module; - reset(); - } - - @Override - protected ContentEntryTreeEditor createContentEntryTreeEditor(Project project) { - return new MyContentEntryTreeEditor(project, getEditHandlers()); - } - - @Override - protected List<ContentEntry> addContentEntries(VirtualFile[] files) { - List<ContentEntry> entries = super.addContentEntries(files); - addContentEntryPanels(entries.toArray(new ContentEntry[entries.size()])); - return entries; - } - - @Override - public void reset() { - if (myFilePointersDisposable != null) { - Disposer.dispose(myFilePointersDisposable); - } - myTemplateRoots.clear(); - - myFilePointersDisposable = Disposer.newDisposable(); - final TemplatesService instance = TemplatesService.getInstance(myModule); - if (instance != null) { - final List<VirtualFile> folders = instance.getTemplateFolders(); - for (VirtualFile folder : folders) { - ContentEntry contentEntry = findContentEntryForFile(folder); - if (contentEntry != null) { - myTemplateRoots.putValue(contentEntry, VirtualFilePointerManager.getInstance().create(folder, myFilePointersDisposable, - DUMMY_LISTENER)); - } - } - } - - if (myRootTreeEditor != null) { - ContentEntryEditor editor = myRootTreeEditor.getContentEntryEditor(); - if(editor!=null) editor.update(); - myRootTreeEditor.update(); - } - } - - @Nullable - private ContentEntry findContentEntryForFile(VirtualFile virtualFile) { - for (ContentEntry contentEntry : getModel().getContentEntries()) { - final VirtualFile file = contentEntry.getFile(); - if (file != null && VfsUtilCore.isAncestor(file, virtualFile, false)) { - return contentEntry; - } - } - return null; - } - - @Override - public void disposeUIResources() { - super.disposeUIResources(); - if (myFilePointersDisposable != null) { - Disposer.dispose(myFilePointersDisposable); - } - } - - @Override - public void apply() throws ConfigurationException { - super.apply(); - List<VirtualFile> templateRoots = getCurrentState(); - TemplatesService.getInstance(myModule).setTemplateFolders(templateRoots.toArray(new VirtualFile[templateRoots.size()])); - } - - private List<VirtualFile> getCurrentState() { - List<VirtualFile> result = new ArrayList<VirtualFile>(); - for (ContentEntry entry : myTemplateRoots.keySet()) { - for (VirtualFilePointer filePointer : myTemplateRoots.get(entry)) { - result.add(filePointer.getFile()); - } - } - return result; - } - - @Override - public boolean isModified() { - if (super.isModified()) return true; - final TemplatesService templatesService = TemplatesService.getInstance(myModule); - if (templatesService != null) { - List<VirtualFile> original = templatesService.getTemplateFolders(); - List<VirtualFile> current = getCurrentState(); - - if (!Comparing.haveEqualElements(original, current)) return true; - - } - return false; - } - - @Override - protected MyContentEntryEditor createContentEntryEditor(String contentEntryUrl) { - return new MyContentEntryEditor(contentEntryUrl, getEditHandlers()); - } - - protected class MyContentEntryEditor extends ContentEntryEditor { - private final EventDispatcher<ChangeListener> myEventDispatcher = EventDispatcher.create(ChangeListener.class); - - public MyContentEntryEditor(String contentEntryUrl, List<ModuleSourceRootEditHandler<?>> handlers) { - super(contentEntryUrl, handlers); - } - - @Override - protected ModifiableRootModel getModel() { - return MyCommonContentEntriesEditor.this.getModel(); - } - - public void addListener(ChangeListener changeListener) { - myEventDispatcher.addListener(changeListener); - } - - public void removeListener(ChangeListener changeListener) { - myEventDispatcher.removeListener(changeListener); - } - - @Override - protected ContentRootPanel createContentRootPane() { - return new MyContentRootPanel(); - } - - @Override - public void deleteContentFolder(ContentEntry contentEntry, ContentFolder folder) { - if (folder instanceof TemplateRootFolder) { - final VirtualFile file = folder.getFile(); - if (file != null) { - removeTemplateRoot(file); - } - } - else { - super.deleteContentFolder(contentEntry, folder); - } - } - - public void addTemplateRoot(@NotNull final VirtualFile file) { - final VirtualFilePointer root = VirtualFilePointerManager.getInstance().create(file, myFilePointersDisposable, DUMMY_LISTENER); - myTemplateRoots.putValue(getContentEntry(), root); - myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); - update(); - } - - public void removeTemplateRoot(@NotNull final VirtualFile file) { - final VirtualFilePointer root = getTemplateRoot(file); - if (root != null) { - myTemplateRoots.remove(getContentEntry(), root); - myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this)); - update(); - } - } - - public boolean hasTemplateRoot(@NotNull final VirtualFile file) { - return getTemplateRoot(file) != null; - } - - @Nullable - public VirtualFilePointer getTemplateRoot(@NotNull final VirtualFile file) { - for (VirtualFilePointer filePointer : myTemplateRoots.get(getContentEntry())) { - if (Comparing.equal(filePointer.getFile(), file)) { - return filePointer; - } - } - return null; - } - - protected class MyContentRootPanel extends ContentRootPanel { - public MyContentRootPanel() { - super(MyContentEntryEditor.this, getEditHandlers()); - } - - @Override - @NotNull - protected ContentEntryImpl getContentEntry() { - //noinspection ConstantConditions - return (ContentEntryImpl)MyContentEntryEditor.this.getContentEntry(); - } - - @Override - protected void addFolderGroupComponents() { - super.addFolderGroupComponents(); - if (!myTemplateRoots.get(getContentEntry()).isEmpty()) { - final List<TemplateRootFolder> folders = new ArrayList<TemplateRootFolder>(myTemplateRoots.size()); - for (VirtualFilePointer root : myTemplateRoots.get(getContentEntry())) { - folders.add(new TemplateRootFolder(root, getContentEntry())); - } - final JComponent sourcesComponent = createFolderGroupComponent("Template Folders", - folders.toArray(new ContentFolder[folders.size()]), - TEMPLATES_COLOR, null); - this.add(sourcesComponent, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH, - GridBagConstraints.HORIZONTAL, new Insets(0, 0, 10, 0), 0, 0)); - } - } - } - } - } - - private static class TemplateRootFolder extends ContentFolderBaseImpl { - protected TemplateRootFolder(@NotNull VirtualFilePointer filePointer, @NotNull ContentEntryImpl contentEntry) { - super(filePointer, contentEntry); - } - } } diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonPathEditor.java b/python/ide/src/com/jetbrains/python/configuration/PythonPathEditor.java index 33169a79d267..0512bb051bf7 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PythonPathEditor.java +++ b/python/ide/src/com/jetbrains/python/configuration/PythonPathEditor.java @@ -126,7 +126,7 @@ public class PythonPathEditor extends SdkPathEditor { @Override protected void addToolbarButtons(ToolbarDecorator toolbarDecorator) { - AnActionButton reloadButton = new AnActionButton("Reload List of Paths", AllIcons.Actions.Refresh) { + AnActionButton reloadButton = new AnActionButton("Reload list of paths", AllIcons.Actions.Refresh) { @Override public void actionPerformed(AnActionEvent e) { onReloadButtonClicked(); diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java index b0ca6dbff65f..213b0e1e69d5 100644 --- a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java +++ b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java @@ -435,7 +435,7 @@ public class PythonSdkDetailsDialog extends DialogWrapper { private class ShowPathButton extends AnActionButton implements DumbAware { public ShowPathButton() { - super("Show path for the selected interpreter", AllIcons.Actions.ShowAsTree); + super("Show paths for the selected interpreter", AllIcons.Actions.ShowAsTree); } @Override diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java index dd68cdb6ed2f..1ad9cf7ececc 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/AbstractProjectSettingsStep.java @@ -61,6 +61,7 @@ import java.util.List; abstract public class AbstractProjectSettingsStep extends AbstractActionWithPanel implements DumbAware { protected final DirectoryProjectGenerator myProjectGenerator; private final NullableConsumer<AbstractProjectSettingsStep> myCallback; + private final boolean myIsWelcomeScreen; private PythonSdkChooserCombo mySdkCombo; private boolean myInstallFramework; private TextFieldWithBrowseButton myLocationField; @@ -70,10 +71,13 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane private AnAction myCreateAction; private Sdk mySdk; - public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, NullableConsumer<AbstractProjectSettingsStep> callback) { + public AbstractProjectSettingsStep(DirectoryProjectGenerator projectGenerator, + NullableConsumer<AbstractProjectSettingsStep> callback, + boolean isWelcomeScreen) { super(); myProjectGenerator = projectGenerator; myCallback = callback; + myIsWelcomeScreen = isWelcomeScreen; myProjectDirectory = FileUtil.findSequentNonexistentFile(new File(ProjectUtil.getBaseDir()), "untitled", ""); if (myProjectGenerator instanceof WebProjectTemplate) { ((WebProjectTemplate)myProjectGenerator).getPeer().addSettingsStateListener(new WebProjectGenerator.SettingsStateListener() { @@ -109,17 +113,12 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane @Override public JPanel createPanel() { final JPanel basePanel = createBasePanel(); - final JPanel mainPanel = new JPanel(new BorderLayout()) { - @Override - protected void paintComponent(Graphics g) { - myLocationField.requestFocus(); - } - }; + final JPanel mainPanel = new JPanel(new BorderLayout()); final JPanel scrollPanel = new JPanel(new BorderLayout()); final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME); - final int height = generators.length == 0 ? 150 : 400; + final int height = generators.length == 0 && !myIsWelcomeScreen ? 150 : 400; mainPanel.setPreferredSize(new Dimension(mainPanel.getPreferredSize().width, height)); myErrorLabel = new JLabel(""); myErrorLabel.setForeground(JBColor.RED); @@ -273,6 +272,7 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane } public boolean checkValid() { + if (myLocationField == null) return true; final String projectName = myLocationField.getText(); setErrorText(null); myInstallFramework = false; @@ -367,22 +367,6 @@ abstract public class AbstractProjectSettingsStep extends AbstractActionWithPane myErrorLabel.setForeground(MessageType.WARNING.getTitleForeground()); } - public void selectCompatiblePython() { - //DirectoryProjectGenerator generator = getProjectGenerator(); - //if (generator instanceof PyFrameworkProjectGenerator && !((PyFrameworkProjectGenerator)generator).supportsPython3()) { - // Sdk sdk = getSdk(); - // if (sdk != null && PythonSdkType.getLanguageLevelForSdk(sdk).isPy3K()) { - // Sdk python2Sdk = PythonSdkType.findPython2Sdk(null); - // if (python2Sdk != null) { - // mySdkCombo.getComboBox().setSelectedItem(python2Sdk); - // mySdkCombo.getComboBox().revalidate(); - // mySdkCombo.getComboBox().repaint(); - // - // } - // } - //} - } - private static boolean acceptsRemoteSdk(DirectoryProjectGenerator generator) { if (generator instanceof PyFrameworkProjectGenerator) { return ((PyFrameworkProjectGenerator)generator).acceptsRemoteSdk(); diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java new file mode 100644 index 000000000000..2aa9a391512f --- /dev/null +++ b/python/ide/src/com/jetbrains/python/newProject/actions/GenerateProjectCallback.java @@ -0,0 +1,159 @@ +/* + * 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.newProject.actions; + +import com.intellij.ide.GeneralSettings; +import com.intellij.ide.util.projectWizard.WebProjectTemplate; +import com.intellij.internal.statistic.UsageTrigger; +import com.intellij.internal.statistic.beans.ConvertUsagesUtil; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.projectRoots.ProjectJdkTable; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.projectRoots.SdkAdditionalData; +import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil; +import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.platform.DirectoryProjectGenerator; +import com.intellij.platform.PlatformProjectOpenProcessor; +import com.intellij.projectImport.ProjectOpenedCallback; +import com.intellij.util.NullableConsumer; +import com.jetbrains.python.configuration.PyConfigurableInterpreterList; +import com.jetbrains.python.newProject.PyNewProjectSettings; +import com.jetbrains.python.newProject.PythonProjectGenerator; +import com.jetbrains.python.sdk.PyDetectedSdk; +import com.jetbrains.python.sdk.PySdkService; +import com.jetbrains.python.sdk.PythonSdkAdditionalData; +import com.jetbrains.python.sdk.PythonSdkType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.List; + +public class GenerateProjectCallback implements NullableConsumer<AbstractProjectSettingsStep> { + private static final Logger LOG = Logger.getInstance(GenerateProjectCallback.class); + @Nullable private final Runnable myRunnable; + + public GenerateProjectCallback(@Nullable final Runnable runnable) { + + myRunnable = runnable; + } + + @Override + public void consume(@Nullable AbstractProjectSettingsStep settingsStep) { + if (myRunnable != null) { + myRunnable.run(); + } + if (settingsStep == null) return; + + Sdk sdk = settingsStep.getSdk(); + final Project project = ProjectManager.getInstance().getDefaultProject(); + final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel(); + if (sdk instanceof PyDetectedSdk) { + final String name = sdk.getName(); + VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() { + @Override + public VirtualFile compute() { + return LocalFileSystem.getInstance().refreshAndFindFileByPath(name); + } + }); + PySdkService.getInstance().solidifySdk(sdk); + sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null, + null); + model.addSdk(sdk); + settingsStep.setSdk(sdk); + try { + model.apply(); + } + catch (ConfigurationException exception) { + LOG.error("Error adding detected python interpreter " + exception.getMessage()); + } + } + Project newProject = generateProject(project, settingsStep); + if (newProject != null) { + SdkConfigurationUtil.setDirectoryProjectSdk(newProject, sdk); + final List<Sdk> sdks = PythonSdkType.getAllSdks(); + for (Sdk s : sdks) { + final SdkAdditionalData additionalData = s.getSdkAdditionalData(); + if (additionalData instanceof PythonSdkAdditionalData) { + ((PythonSdkAdditionalData)additionalData).reassociateWithCreatedProject(newProject); + } + } + } + } + + @Nullable + private Project generateProject(@NotNull final Project project, @NotNull final AbstractProjectSettingsStep settings) { + final DirectoryProjectGenerator generator = settings.getProjectGenerator(); + final File location = new File(settings.getProjectLocation()); + if (!location.exists() && !location.mkdirs()) { + Messages.showErrorDialog(project, "Cannot create directory '" + location + "'", "Create Project"); + return null; + } + + final VirtualFile baseDir = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() { + public VirtualFile compute() { + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(location); + } + }); + LOG.assertTrue(baseDir != null, "Couldn't find '" + location + "' in VFS"); + baseDir.refresh(false, true); + + if (baseDir.getChildren().length > 0) { + int rc = Messages.showYesNoDialog(project, + "The directory '" + location + + "' is not empty. Would you like to create a project from existing sources instead?", + "Create New Project", Messages.getQuestionIcon()); + if (rc == Messages.YES) { + return PlatformProjectOpenProcessor.getInstance().doOpenProject(baseDir, null, false); + } + } + + String generatorName = generator == null ? "empty" : ConvertUsagesUtil.ensureProperKey(generator.getName()); + UsageTrigger.trigger("NewDirectoryProjectAction." + generatorName); + + GeneralSettings.getInstance().setLastProjectCreationLocation(location.getParent()); + + return PlatformProjectOpenProcessor.doOpenProject(baseDir, null, false, -1, new ProjectOpenedCallback() { + @Override + public void projectOpened(Project project, Module module) { + if (generator != null) { + Object projectSettings = null; + if (generator instanceof PythonProjectGenerator) { + projectSettings = ((PythonProjectGenerator)generator).getProjectSettings(); + } + else if (generator instanceof WebProjectTemplate) { + projectSettings = ((WebProjectTemplate)generator).getPeer().getSettings(); + } + if (projectSettings instanceof PyNewProjectSettings) { + ((PyNewProjectSettings)projectSettings).setSdk(settings.getSdk()); + ((PyNewProjectSettings)projectSettings).setInstallFramework(settings.installFramework()); + } + //noinspection unchecked + generator.generateProject(project, baseDir, projectSettings, module); + } + } + }, false); + } +} diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java index a0c5f6e52fbf..ca0f3608a5d9 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PluginSpecificProjectsStep.java @@ -27,11 +27,11 @@ import java.util.List; public class PluginSpecificProjectsStep extends DefaultActionGroup implements DumbAware { public PluginSpecificProjectsStep(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback, - @NotNull final List<DirectoryProjectGenerator> projectGenerators) { + @NotNull final List<DirectoryProjectGenerator> projectGenerators, boolean isWelcomeScreen) { super("Plugin-specific", true); getTemplatePresentation().setIcon(AllIcons.Nodes.PluginLogo); for (DirectoryProjectGenerator generator : projectGenerators) { - add(new ProjectSpecificAction(callback, generator)); + add(new ProjectSpecificAction(callback, generator, isWelcomeScreen)); } } } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java index 4397a090b253..fbb65f0fbe9e 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificAction.java @@ -28,10 +28,16 @@ public class ProjectSpecificAction extends DefaultActionGroup implements DumbAwa private final ProjectSpecificSettingsStep mySettings; public ProjectSpecificAction(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback, - @NotNull final DirectoryProjectGenerator projectGenerator) { - super(projectGenerator.getName(), true); + @NotNull final DirectoryProjectGenerator projectGenerator, boolean isWelcomeScreen) { + this(callback, projectGenerator, projectGenerator.getName(), isWelcomeScreen); + } + + public ProjectSpecificAction(@NotNull final NullableConsumer<AbstractProjectSettingsStep> callback, + @NotNull final DirectoryProjectGenerator projectGenerator, + @NotNull final String name, boolean isWelcomeScreen) { + super(name, true); getTemplatePresentation().setIcon(projectGenerator.getLogo()); - mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback); + mySettings = new ProjectSpecificSettingsStep(projectGenerator, callback, isWelcomeScreen); add(mySettings); } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 5e60601399bb..b85a06e0daa6 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -31,8 +31,8 @@ import javax.swing.*; public class ProjectSpecificSettingsStep extends AbstractProjectSettingsStep implements DumbAware { public ProjectSpecificSettingsStep(@NotNull final DirectoryProjectGenerator projectGenerator, - @NotNull final NullableConsumer<AbstractProjectSettingsStep> callback) { - super(projectGenerator, callback); + @NotNull final NullableConsumer<AbstractProjectSettingsStep> callback, boolean isWelcomeScreen) { + super(projectGenerator, callback, isWelcomeScreen); } @Override diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java index 4f9f1074df68..0628c6d829c1 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PyCharmNewProjectStep.java @@ -16,153 +16,33 @@ package com.jetbrains.python.newProject.actions; import com.google.common.collect.Lists; -import com.intellij.ide.GeneralSettings; -import com.intellij.ide.util.projectWizard.WebProjectTemplate; -import com.intellij.internal.statistic.UsageTrigger; -import com.intellij.internal.statistic.beans.ConvertUsagesUtil; import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; -import com.intellij.openapi.projectRoots.ProjectJdkTable; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.projectRoots.SdkAdditionalData; -import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil; -import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; -import com.intellij.platform.PlatformProjectOpenProcessor; -import com.intellij.projectImport.ProjectOpenedCallback; import com.intellij.util.NullableConsumer; -import com.jetbrains.python.configuration.PyConfigurableInterpreterList; import com.jetbrains.python.newProject.PyFrameworkProjectGenerator; -import com.jetbrains.python.newProject.PyNewProjectSettings; import com.jetbrains.python.newProject.PythonBaseProjectGenerator; import com.jetbrains.python.newProject.PythonProjectGenerator; -import com.jetbrains.python.sdk.PyDetectedSdk; -import com.jetbrains.python.sdk.PySdkService; -import com.jetbrains.python.sdk.PythonSdkAdditionalData; -import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAware { - private static final Logger LOG = Logger.getInstance(PyCharmNewProjectStep.class); public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable) { - super(name, true); - - final NullableConsumer<AbstractProjectSettingsStep> callback = new NullableConsumer<AbstractProjectSettingsStep>() { - @Override - public void consume(@Nullable AbstractProjectSettingsStep settingsStep) { - if (runnable != null) - runnable.run(); - if (settingsStep == null) return; - - Sdk sdk = settingsStep.getSdk(); - final Project project = ProjectManager.getInstance().getDefaultProject(); - final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel(); - if (sdk instanceof PyDetectedSdk) { - final String name = sdk.getName(); - VirtualFile sdkHome = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() { - @Override - public VirtualFile compute() { - return LocalFileSystem.getInstance().refreshAndFindFileByPath(name); - } - }); - PySdkService.getInstance().solidifySdk(sdk); - sdk = SdkConfigurationUtil.setupSdk(ProjectJdkTable.getInstance().getAllJdks(), sdkHome, PythonSdkType.getInstance(), true, null, - null); - model.addSdk(sdk); - settingsStep.setSdk(sdk); - try { - model.apply(); - } - catch (ConfigurationException exception) { - LOG.error("Error adding detected python interpreter " + exception.getMessage()); - } - } - Project newProject = generateProject(project, settingsStep); - if (newProject != null) { - SdkConfigurationUtil.setDirectoryProjectSdk(newProject, sdk); - final List<Sdk> sdks = PythonSdkType.getAllSdks(); - for (Sdk s : sdks) { - final SdkAdditionalData additionalData = s.getSdkAdditionalData(); - if (additionalData instanceof PythonSdkAdditionalData) { - ((PythonSdkAdditionalData)additionalData).reassociateWithCreatedProject(newProject); - } - } - } - } - - @Nullable - private Project generateProject(@NotNull final Project project, @NotNull final AbstractProjectSettingsStep settings) { - final DirectoryProjectGenerator generator = settings.getProjectGenerator(); - final File location = new File(settings.getProjectLocation()); - if (!location.exists() && !location.mkdirs()) { - Messages.showErrorDialog(project, "Cannot create directory '" + location + "'", "Create Project"); - return null; - } - - final VirtualFile baseDir = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() { - public VirtualFile compute() { - return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(location); - } - }); - LOG.assertTrue(baseDir != null, "Couldn't find '" + location + "' in VFS"); - baseDir.refresh(false, true); - - if (baseDir.getChildren().length > 0) { - int rc = Messages.showYesNoDialog(project, - "The directory '" + location + - "' is not empty. Would you like to create a project from existing sources instead?", - "Create New Project", Messages.getQuestionIcon()); - if (rc == Messages.YES) { - return PlatformProjectOpenProcessor.getInstance().doOpenProject(baseDir, null, false); - } - } + this(name, runnable, false); + } - String generatorName = generator == null ? "empty" : ConvertUsagesUtil.ensureProperKey(generator.getName()); - UsageTrigger.trigger("NewDirectoryProjectAction." + generatorName); + public PyCharmNewProjectStep(@NotNull final String name, @Nullable final Runnable runnable, boolean isWelcomeScreen) { + super(name, true); - GeneralSettings.getInstance().setLastProjectCreationLocation(location.getParent()); + final NullableConsumer<AbstractProjectSettingsStep> callback = new GenerateProjectCallback(runnable); - return PlatformProjectOpenProcessor.doOpenProject(baseDir, null, false, -1, new ProjectOpenedCallback() { - @Override - public void projectOpened(Project project, Module module) { - if (generator != null) { - Object projectSettings = null; - if (generator instanceof PythonProjectGenerator) - projectSettings = ((PythonProjectGenerator)generator).getProjectSettings(); - else if (generator instanceof WebProjectTemplate) { - projectSettings = ((WebProjectTemplate)generator).getPeer().getSettings(); - } - if (projectSettings instanceof PyNewProjectSettings) { - ((PyNewProjectSettings)projectSettings).setSdk(settings.getSdk()); - ((PyNewProjectSettings)projectSettings).setInstallFramework(settings.installFramework()); - } - //noinspection unchecked - generator.generateProject(project, baseDir, projectSettings, module); - } - } - }, false); - } - }; - - final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator()); + final ProjectSpecificAction action = new ProjectSpecificAction(callback, new PythonBaseProjectGenerator(), isWelcomeScreen); add(action); final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME); @@ -181,19 +61,17 @@ public class PyCharmNewProjectStep extends DefaultActionGroup implements DumbAwa List<DirectoryProjectGenerator> pluginSpecificGenerators = Lists.newArrayList(); for (DirectoryProjectGenerator generator : generators) { if (generator instanceof PythonProjectGenerator) - add(new ProjectSpecificAction(callback, generator)); + add(new ProjectSpecificAction(callback, generator, isWelcomeScreen)); else pluginSpecificGenerators.add(generator); } if (!pluginSpecificGenerators.isEmpty()) { - add(new PluginSpecificProjectsStep(callback, pluginSpecificGenerators)); + add(new PluginSpecificProjectsStep(callback, pluginSpecificGenerators, isWelcomeScreen)); } } public PyCharmNewProjectStep() { - this("Select Project Type", null); - + this("Select Project Type", null, true); } - } |