Added a project create dialog

This commit is contained in:
meanmail
2017-04-12 22:45:58 +07:00
parent f8be70c916
commit 8667ae60ab
14 changed files with 676 additions and 197 deletions
@@ -0,0 +1,96 @@
/*
* Copyright 2000-2017 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.edu.common.newproject;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.util.BooleanFunction;
import com.jetbrains.edu.learning.newproject.EduCourseProjectGenerator;
import com.jetbrains.edu.learning.PyStudyDirectoryProjectGenerator;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.python.newProject.PyNewProjectSettings;
import com.jetbrains.python.newProject.PythonProjectGenerator;
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author meanmail
*/
public class PyEduCourseProjectGenerator implements EduCourseProjectGenerator {
private final PyStudyDirectoryProjectGenerator generator;
public PyEduCourseProjectGenerator() {
this.generator = new PyStudyDirectoryProjectGenerator();
}
@NotNull
@Override
public DirectoryProjectGenerator getDirectoryProjectGenerator() {
return generator;
}
@Nullable
@Override
public Object getProjectSettings() {
return generator.getProjectSettings();
}
@Override
public void setCourse(@NotNull Course course) {
generator.setSelectedCourse(course);
}
@Override
public ValidationResult validate(@NotNull String path) {
generator.setValidationResult(ValidationResult.OK);
return generator.validate(path);
}
@Override
public boolean beforeProjectGenerated() {
BooleanFunction<PythonProjectGenerator> function =
generator.beforeProjectGenerated(null);
return function != null && function.fun(generator);
}
@Override
public void afterProjectGenerated(@NotNull Project project) {
PyNewProjectSettings settings = (PyNewProjectSettings)generator.getProjectSettings();
Sdk sdk = settings.getSdk();
if (sdk == null) {
generator.createAndAddVirtualEnv(project, settings);
sdk = settings.getSdk();
}
SdkConfigurationUtil.setDirectoryProjectSdk(project, sdk);
final List<Sdk> sdks = PythonSdkType.getAllSdks();
for (Sdk s : sdks) {
final SdkAdditionalData additionalData = s.getSdkAdditionalData();
if (additionalData instanceof PythonSdkAdditionalData) {
((PythonSdkAdditionalData)additionalData).reassociateWithCreatedProject(project);
}
}
}
}
@@ -5,8 +5,6 @@ import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.ide.util.DirectoryUtil;
import com.intellij.ide.util.projectWizard.AbstractNewProjectDialog;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -16,11 +14,11 @@ import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.util.Consumer;
import com.intellij.util.PathUtil;
import com.jetbrains.edu.common.newproject.PyEduCourseProjectGenerator;
import com.jetbrains.edu.learning.newproject.EduCourseProjectGenerator;
import com.jetbrains.edu.coursecreator.settings.CCSettings;
import com.jetbrains.edu.learning.actions.StudyCheckAction;
import com.jetbrains.edu.learning.builtInServer.EduBuiltInServerNewProjectStep;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
@@ -150,16 +148,7 @@ public class PyEduPluginConfigurator implements EduPluginConfigurator {
}
@Override
public boolean createCourseProject(@NotNull Course course, @Nullable Consumer<Project> onCreated) {
ApplicationManager.getApplication().invokeAndWait(() -> {
AbstractNewProjectDialog dlg = new AbstractNewProjectDialog() {
@Override
protected DefaultActionGroup createRootStep() {
return new EduBuiltInServerNewProjectStep(course, onCreated);
}
};
dlg.show();
});
return true;
public EduCourseProjectGenerator getEduCourseProjectGenerator() {
return new PyEduCourseProjectGenerator();
}
}
@@ -23,7 +23,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
import com.intellij.util.BooleanFunction;
import com.intellij.util.Consumer;
import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.RemoteCourse;
@@ -57,17 +56,16 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
private static final Logger LOG = Logger.getInstance(PyStudyDirectoryProjectGenerator.class.getName());
private final StudyProjectGenerator myGenerator;
private static final String NO_PYTHON_INTERPRETER = "<html><u>Add</u> python interpreter.</html>";
private final Consumer<Project> myOnCreated;
private final boolean isLocal;
public ValidationResult myValidationResult = new ValidationResult("selected course is not valid");
private final StudyNewProjectPanel mySettingsPanel;
@SuppressWarnings("unused") // used on startup
public PyStudyDirectoryProjectGenerator() {
this(false);
}
public PyStudyDirectoryProjectGenerator(boolean isLocal, @Nullable Consumer<Project> onCreated) {
myOnCreated = onCreated;
public PyStudyDirectoryProjectGenerator(boolean isLocal) {
this.isLocal = isLocal;
myGenerator = new StudyProjectGenerator();
myGenerator.addSettingsStateListener(new StudyProjectGenerator.SettingsListener() {
@Override
@@ -75,47 +73,6 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
setValidationResult(result);
}
});
mySettingsPanel = new StudyNewProjectPanel(myGenerator, isLocal);
mySettingsPanel.registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
throw new UnsupportedOperationException();
}
public void validate() {
ApplicationManager.getApplication().invokeLater(() -> fireStateChanged());
}
});
addErrorLabelMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
final Object selectedItem = mySettingsPanel.getCoursesComboBox().getSelectedItem();
if (selectedItem != null && ((Course)selectedItem).isAdaptive() && !myGenerator.isLoggedIn()) {
mySettingsPanel.showLoginDialog(false, "Signing In");
}
}
@Override
public void mouseEntered(MouseEvent e) {
final Object selectedItem = mySettingsPanel.getCoursesComboBox().getSelectedItem();
if (selectedItem != null && ((Course)selectedItem).isAdaptive() && !myGenerator.isLoggedIn()) {
e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
}
@Override
public void mouseExited(MouseEvent e) {
final Course selectedItem = (Course)mySettingsPanel.getCoursesComboBox().getSelectedItem();
if (selectedItem != null && selectedItem.isAdaptive() && !myGenerator.isLoggedIn()) {
e.getComponent().setCursor(Cursor.getDefaultCursor());
}
}
});
}
public PyStudyDirectoryProjectGenerator(boolean isLocal) {
this(isLocal, null);
}
@Nls
@@ -138,6 +95,10 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
@NotNull Module module,
@Nullable PyProjectSynchronizer synchronizer) {
myGenerator.generateProject(project, baseDir);
createTestHelper(project, baseDir);
}
private static void createTestHelper(@NotNull Project project, @NotNull VirtualFile baseDir) {
final String testHelper = EduNames.TEST_HELPER;
if (baseDir.findChild(testHelper) != null) return;
final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate("test_helper");
@@ -149,14 +110,6 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
catch (Exception exception) {
LOG.error("Can't copy test_helper.py " + exception.getMessage());
}
doCreated(project);
}
protected void doCreated(@NotNull Project project) {
if (myOnCreated != null) {
myOnCreated.consume(project);
}
}
@NotNull
@@ -178,6 +131,45 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
@Nullable
@Override
public JPanel extendBasePanel() throws ProcessCanceledException {
StudyNewProjectPanel mySettingsPanel = new StudyNewProjectPanel(myGenerator, isLocal);
mySettingsPanel.registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
throw new UnsupportedOperationException();
}
public void validate() {
ApplicationManager.getApplication().invokeLater(() -> fireStateChanged());
}
});
addErrorLabelMouseListener(new MouseAdapter() {
private boolean isCourseAdaptiveAndNotLogged() {
Course course = myGenerator.getSelectedCourse();
return course != null && course.isAdaptive() && !myGenerator.isLoggedIn();
}
@Override
public void mouseClicked(MouseEvent e) {
if (isCourseAdaptiveAndNotLogged()) {
mySettingsPanel.showLoginDialog(false, "Signing In");
}
}
@Override
public void mouseEntered(MouseEvent e) {
if (isCourseAdaptiveAndNotLogged()) {
e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
}
@Override
public void mouseExited(MouseEvent e) {
if (isCourseAdaptiveAndNotLogged()) {
e.getComponent().setCursor(Cursor.getDefaultCursor());
}
}
});
return mySettingsPanel;
}
@@ -199,7 +191,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
public BooleanFunction<PythonProjectGenerator> beforeProjectGenerated(@Nullable Sdk sdk) {
return generator -> {
final List<Integer> enrolledCoursesIds = myGenerator.getEnrolledCoursesIds();
final Course course = (Course)mySettingsPanel.getCoursesComboBox().getSelectedItem();
final Course course = myGenerator.getSelectedCourse();
if (course == null || !(course instanceof RemoteCourse)) return true;
if (((RemoteCourse)course).getId() > 0 && !enrolledCoursesIds.contains(((RemoteCourse)course).getId())) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
@@ -207,7 +199,6 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator<PyN
return StudyUtils.execCancelable(() -> EduStepicConnector.enrollToCourse(((RemoteCourse)course).getId(),
StudySettings.getInstance().getUser()));
}, "Creating Course", true, ProjectManager.getInstance().getDefaultProject());
}
return true;
};
@@ -1,64 +0,0 @@
/*
* Copyright 2000-2017 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.edu.learning.builtInServer;
import com.intellij.openapi.project.Project;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.util.Consumer;
import com.jetbrains.edu.learning.PyStudyDirectoryProjectGenerator;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
import com.jetbrains.python.newProject.steps.PyCharmNewProjectStep;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
* @author meanmail
*/
public class EduBuiltInServerNewProjectStep extends PyCharmNewProjectStep {
public EduBuiltInServerNewProjectStep(@NotNull Course course, @Nullable Consumer<Project> onCreated) {
super(new EduBuiltInServerNewProjectStep.MyCustomization(course, onCreated));
}
protected static class MyCustomization extends PyCharmNewProjectStep.Customization {
private final Course myCourse;
private final PyStudyDirectoryProjectGenerator myGenerator;
public MyCustomization(@NotNull Course course, @Nullable Consumer<Project> onCreated) {
myCourse = course;
myGenerator = new PyStudyDirectoryProjectGenerator(true, onCreated);
}
@NotNull
@Override
protected DirectoryProjectGenerator[] getProjectGenerators() {
return new DirectoryProjectGenerator[] {};
}
@NotNull
@Override
protected DirectoryProjectGenerator createEmptyProjectGenerator() {
StudyProjectGenerator generator = myGenerator.getGenerator();
List<Course> courses = Collections.singletonList(myCourse);
generator.setCourses(courses);
generator.setSelectedCourse(myCourse);
return myGenerator;
}
}
}