5d786bf9b24ff0821d46a3200419a8a9ea870ec0
[idea/community.git] / python / educational-python / course-creator-python / src / com / jetbrains / edu / coursecreator / PyCCProjectGenerator.java
1 package com.jetbrains.edu.coursecreator;
2
3 import com.intellij.facet.ui.FacetEditorValidator;
4 import com.intellij.facet.ui.FacetValidatorsManager;
5 import com.intellij.facet.ui.ValidationResult;
6 import com.intellij.ide.fileTemplates.FileTemplate;
7 import com.intellij.ide.fileTemplates.FileTemplateManager;
8 import com.intellij.ide.fileTemplates.FileTemplateUtil;
9 import com.intellij.openapi.command.WriteCommandAction;
10 import com.intellij.openapi.diagnostic.Logger;
11 import com.intellij.openapi.module.Module;
12 import com.intellij.openapi.progress.ProcessCanceledException;
13 import com.intellij.openapi.project.Project;
14 import com.intellij.openapi.util.io.FileUtil;
15 import com.intellij.openapi.vfs.VirtualFile;
16 import com.intellij.platform.DirectoryProjectGenerator;
17 import com.intellij.psi.PsiDirectory;
18 import com.intellij.psi.PsiManager;
19 import com.jetbrains.edu.coursecreator.actions.CCCreateLesson;
20 import com.jetbrains.edu.coursecreator.actions.CCCreateTask;
21 import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel;
22 import com.jetbrains.edu.learning.StudyProjectComponent;
23 import com.jetbrains.edu.learning.StudyTaskManager;
24 import com.jetbrains.edu.learning.core.EduNames;
25 import com.jetbrains.edu.learning.courseFormat.Course;
26 import com.jetbrains.edu.learning.statistics.EduUsagesCollector;
27 import com.jetbrains.python.PythonLanguage;
28 import com.jetbrains.python.newProject.PythonProjectGenerator;
29 import icons.CourseCreatorPythonIcons;
30 import org.jetbrains.annotations.Nls;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import javax.swing.*;
35 import java.io.File;
36
37 import static com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator.OUR_COURSES_DIR;
38
39
40 public class PyCCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator {
41   private static final Logger LOG = Logger.getInstance(PyCCProjectGenerator.class);
42   private CCNewProjectPanel mySettingsPanel;
43
44   @Nls
45   @NotNull
46   @Override
47   public String getName() {
48     return "Course creation";
49   }
50
51   @Nullable
52   @Override
53   public Icon getLogo() {
54     return CourseCreatorPythonIcons.CourseCreationProjectType;
55   }
56
57   @Override
58   public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
59                               @Nullable Object settings, @NotNull Module module) {
60     generateProject(project, baseDir, mySettingsPanel);
61   }
62
63   public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, CCNewProjectPanel settingsPanel) {
64     final Course course = getCourse(project, settingsPanel);
65     EduUsagesCollector.projectTypeCreated(CCUtils.COURSE_MODE);
66
67     final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir);
68     if (projectDir == null) return;
69     new WriteCommandAction.Simple(project) {
70       @Override
71       protected void run() throws Throwable {
72
73         createTestHelper(project, projectDir);
74
75         PsiDirectory lessonDir = new CCCreateLesson().createItem(null, project, projectDir, course);
76         if (lessonDir == null) {
77           LOG.error("Failed to create lesson");
78           return;
79         }
80         new CCCreateTask().createItem(null, project, lessonDir, course);
81       }
82     }.execute();
83   }
84
85   private static void createTestHelper(@NotNull Project project, PsiDirectory projectDir) {
86     final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate(FileUtil.getNameWithoutExtension(EduNames.TEST_HELPER));
87     try {
88       FileTemplateUtil.createFromTemplate(template, EduNames.TEST_HELPER, null, projectDir);
89     }
90     catch (Exception ignored) {
91     }
92   }
93
94   @NotNull
95   private static Course getCourse(@NotNull Project project, @NotNull CCNewProjectPanel settingsPanel) {
96     final Course course = new Course();
97     String name = settingsPanel.getName();
98     course.setName(name);
99     course.setAuthorsAsString(settingsPanel.getAuthors());
100     course.setDescription(settingsPanel.getDescription());
101
102     String language = PythonLanguage.getInstance().getID();
103     course.setLanguage(language);
104     course.setCourseMode(CCUtils.COURSE_MODE);
105
106     File courseDir = new File(OUR_COURSES_DIR, name + "-" + project.getName());
107     course.setCourseDirectory(courseDir.getPath());
108
109     StudyTaskManager.getInstance(project).setCourse(course);
110     StudyProjectComponent.getInstance(project).registerStudyToolWindow(course);
111     return course;
112   }
113
114   @NotNull
115   @Override
116   public ValidationResult validate(@NotNull String s) {
117     String message = "";
118     message = mySettingsPanel.getDescription().isEmpty() ? "Enter description" : message;
119     message = mySettingsPanel.getAuthors().length == 0 ? "Enter author name" : message;
120     message = mySettingsPanel.getName().isEmpty() ? "Enter course name" : message;
121     return message.isEmpty() ? ValidationResult.OK : new ValidationResult(message);
122   }
123
124   @Nullable
125   @Override
126   public JPanel extendBasePanel() throws ProcessCanceledException {
127     mySettingsPanel = new CCNewProjectPanel();
128     mySettingsPanel.registerValidators(new FacetValidatorsManager() {
129       public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
130         throw new UnsupportedOperationException();
131       }
132
133       public void validate() {
134         fireStateChanged();
135       }
136     });
137     return mySettingsPanel.getMainPanel();
138   }
139
140   @Override
141   public void locationChanged(@NotNull String newLocation) {
142     mySettingsPanel.getNameField().setText(newLocation);
143   }
144 }