diff --git a/python/edu/course-creator-python/course-creator-python.iml b/python/edu/course-creator-python/course-creator-python.iml index e08d029ad3ce..1f8e332757fd 100644 --- a/python/edu/course-creator-python/course-creator-python.iml +++ b/python/edu/course-creator-python/course-creator-python.iml @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index d5f73de1e69e..7ce529f1e676 100644 --- a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -15,9 +15,9 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; +import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.coursecreator.actions.CCCreateLesson; import com.jetbrains.edu.coursecreator.actions.CCCreateTask; -import com.jetbrains.edu.coursecreator.format.Course; import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; import com.jetbrains.python.newProject.PythonProjectGenerator; import icons.CourseCreatorPythonIcons; @@ -63,7 +63,10 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire @NotNull final String description) { final CCProjectService service = CCProjectService.getInstance(project); - final Course course = new Course(name, author, description); + final Course course = new Course(); + course.setName(name); + course.setAuthor(author); + course.setDescription(description); course.setLanguage("Python"); service.setCourse(course); @@ -79,7 +82,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire catch (Exception ignored) { } DirectoryUtil.createSubdirectories("hints", projectDir, "\\/"); - final PsiDirectory lessonDir = CCCreateLesson.createLessonDir(projectDir, 1, null, null, course); + final PsiDirectory lessonDir = CCCreateLesson.createLessonDir(project, 1, null, null, course); CCCreateTask.createTask(null, project, lessonDir, false); } }.execute(); diff --git a/python/edu/course-creator-python/tests/CCDocumentListenerTest.java b/python/edu/course-creator-python/tests/CCDocumentListenerTest.java index 87e2548a1406..23170c218025 100644 --- a/python/edu/course-creator-python/tests/CCDocumentListenerTest.java +++ b/python/edu/course-creator-python/tests/CCDocumentListenerTest.java @@ -5,9 +5,9 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.util.xmlb.XmlSerializer; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.coursecreator.actions.CCCreateCourseArchive; -import com.jetbrains.edu.coursecreator.format.AnswerPlaceholder; -import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jdom.input.SAXBuilder; import org.jetbrains.annotations.NotNull; @@ -57,7 +57,7 @@ public class CCDocumentListenerTest extends CCTestCase { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - document.replaceString(offset, offset + answerPlaceholder.getReplacementLength(), taskText); + document.replaceString(offset, offset + answerPlaceholder.getPossibleAnswer().length(), taskText); FileDocumentManager.getInstance().saveDocument(document); } }); diff --git a/python/educational/course-creator/course-creator.iml b/python/educational/course-creator/course-creator.iml index 75a2690f8e0f..b54f05e2bd7e 100644 --- a/python/educational/course-creator/course-creator.iml +++ b/python/educational/course-creator/course-creator.iml @@ -5,10 +5,12 @@ + + \ No newline at end of file diff --git a/python/educational/course-creator/resources/META-INF/plugin.xml b/python/educational/course-creator/resources/META-INF/plugin.xml index 3aee001aecbc..200574534a05 100644 --- a/python/educational/course-creator/resources/META-INF/plugin.xml +++ b/python/educational/course-creator/resources/META-INF/plugin.xml @@ -55,7 +55,7 @@ - + diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCAnswerPlaceholderPainter.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCAnswerPlaceholderPainter.java new file mode 100644 index 000000000000..9b2d23682c95 --- /dev/null +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCAnswerPlaceholderPainter.java @@ -0,0 +1,174 @@ +package com.jetbrains.edu.coursecreator; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.editor.markup.*; +import com.intellij.openapi.project.Project; +import com.intellij.ui.JBColor; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.TaskFile; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.List; + +public class CCAnswerPlaceholderPainter { + private CCAnswerPlaceholderPainter() { + + } + + public static void drawHighlighter(@NotNull final AnswerPlaceholder placeholder, @NotNull final Editor editor, boolean useLength) { + drawAnswerPlaceholder(editor, placeholder, useLength, JBColor.BLUE); + //int startOffset = placeholder.getRealStartOffset(editor.getDocument()); + //final int length = placeholder.getLength(); + //final int replacementLength = placeholder.getPossibleAnswer().length(); + //int highlighterLength = useLength ? length : replacementLength; + //int endOffset = startOffset + highlighterLength; + //TextAttributes defaultTestAttributes = + // EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES); + //defaultTestAttributes.setEffectColor(JBColor.BLUE); + //RangeHighlighter highlighter = + // editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, HighlighterLayer.LAST + 1, defaultTestAttributes, + // HighlighterTargetArea.EXACT_RANGE); + //highlighter.setGreedyToLeft(true); + //highlighter.setGreedyToRight(true); + } + + + + public static void drawAnswerPlaceholder(@NotNull final Editor editor, @NotNull final AnswerPlaceholder placeholder, boolean useLength, + @NotNull final JBColor color) { + Document document = editor.getDocument(); + if (useLength && !placeholder.isValid(document)) { + return; + } + EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + final TextAttributes defaultTestAttributes = new TextAttributes(scheme.getDefaultForeground(), scheme.getDefaultBackground(), null, + EffectType.BOXED, Font.PLAIN); + final Project project = editor.getProject(); + assert project != null; + int startOffset = placeholder.getRealStartOffset(document); + final int length = placeholder.getLength(); + final int replacementLength = placeholder.getPossibleAnswerLength(); + int highlighterLength = useLength ? length : replacementLength; + int endOffset = startOffset + highlighterLength; + RangeHighlighter + highlighter = editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, HighlighterLayer.LAST + 1, + defaultTestAttributes, HighlighterTargetArea.EXACT_RANGE); + highlighter.setCustomRenderer(new CustomHighlighterRenderer() { + @Override + public void paint(@NotNull Editor editor, @NotNull RangeHighlighter highlighter, @NotNull Graphics g) { + g.setColor(color); + Point point = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getStartOffset())); + Point pointEnd = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getEndOffset())); + g.drawRect(point.x, point.y - 2, (pointEnd.x - point.x), editor.getLineHeight() + 1); + } + }); + editor.getCaretModel().moveToOffset(startOffset); + highlighter.setGreedyToLeft(true); + highlighter.setGreedyToRight(true); + } + + /* + public static void drawAnswerPlaceholder(@NotNull final Editor editor, AnswerPlaceholder answerPlaceholder) { + Document document = editor.getDocument(); + if (!answerPlaceholder.isValid(document)) { + return; + } + EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + final TextAttributes defaultTestAttributes = new TextAttributes(scheme.getDefaultForeground(), scheme.getDefaultBackground(), null, + EffectType.BOXED, Font.PLAIN); + final Project project = editor.getProject(); + assert project != null; + final JBColor color = StudyTaskManager.getInstance(project).getColor(answerPlaceholder); + int startOffset = answerPlaceholder.getRealStartOffset(document); + RangeHighlighter + highlighter = editor.getMarkupModel().addRangeHighlighter(startOffset, startOffset + answerPlaceholder.getLength(), HighlighterLayer.LAST + 1, + defaultTestAttributes, HighlighterTargetArea.EXACT_RANGE); + highlighter.setCustomRenderer(new CustomHighlighterRenderer() { + @Override + public void paint(@NotNull Editor editor, @NotNull RangeHighlighter highlighter, @NotNull Graphics g) { + g.setColor(color); + Point point = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getStartOffset())); + Point pointEnd = editor.logicalPositionToXY(editor.offsetToLogicalPosition(highlighter.getEndOffset())); + g.drawRect(point.x, point.y - 2, (pointEnd.x - point.x), editor.getLineHeight() + 1); + } + }); + editor.getCaretModel().moveToOffset(startOffset); + highlighter.setGreedyToLeft(true); + highlighter.setGreedyToRight(true); + } + +/* + public static void drawAllWindows(Editor editor, TaskFile taskFile) { + editor.getMarkupModel().removeAllHighlighters(); + for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { + drawAnswerPlaceholder(editor, answerPlaceholder); + } + final Document document = editor.getDocument(); + EditorActionManager.getInstance() + .setReadonlyFragmentModificationHandler(document, new TaskWindowDeleteHandler(editor)); + createGuardedBlocks(editor, taskFile); + editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null); + } + + + *//** + * Marks symbols adjacent to task windows as read-only fragments + *//* + public static void createGuardedBlocks(@NotNull final Editor editor, TaskFile taskFile) { + final Document document = editor.getDocument(); + if (document instanceof DocumentImpl) { + DocumentImpl documentImpl = (DocumentImpl)document; + List blocks = documentImpl.getGuardedBlocks(); + for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { + if (!answerPlaceholder.isValid(document)) { + return; + } + int start = answerPlaceholder.getRealStartOffset(document); + int end = start + answerPlaceholder.getLength(); + if (start != 0) { + createGuardedBlock(editor, blocks, start - 1, start); + } + if (end != document.getTextLength()) { + createGuardedBlock(editor, blocks, end, end + 1); + } + } + } + } +*/ + + public static void createGuardedBlock(Editor editor, List blocks, int start, int end) { + RangeHighlighter rh = editor.getMarkupModel() + .addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE); + blocks.add(rh); + } + + + public static void createGuardedBlocks(@NotNull final Editor editor, TaskFile taskFile) { + for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { + createGuardedBlocks(editor, answerPlaceholder); + } + } + + public static void createGuardedBlocks(@NotNull final Editor editor, AnswerPlaceholder placeholder) { + Document document = editor.getDocument(); + if (document instanceof DocumentImpl) { + DocumentImpl documentImpl = (DocumentImpl)document; + java.util.List blocks = documentImpl.getGuardedBlocks(); + int start = placeholder.getRealStartOffset(document); + int end = start + placeholder.getPossibleAnswer().length(); + if (start != 0) { + createGuardedBlock(editor, blocks, start - 1, start); + } + if (end != document.getTextLength()) { + createGuardedBlock(editor, blocks, end, end + 1); + } + } + } + +} diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java index 3519701a024a..c03a099026a4 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCDocumentListener.java @@ -4,8 +4,9 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.impl.event.DocumentEventImpl; -import com.jetbrains.edu.coursecreator.format.AnswerPlaceholder; -import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.intellij.openapi.util.TextRange; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.TaskFile; import java.util.ArrayList; import java.util.List; @@ -32,7 +33,7 @@ public abstract class CCDocumentListener extends DocumentAdapter { myTaskWindows.clear(); for (AnswerPlaceholder answerPlaceholder : myTaskFile.getAnswerPlaceholders()) { int twStart = answerPlaceholder.getRealStartOffset(document); - int length = useLength() ? answerPlaceholder.getLength() : answerPlaceholder.getReplacementLength(); + int length = useLength() ? answerPlaceholder.getLength() : answerPlaceholder.getPossibleAnswerLength(); int twEnd = twStart + length; myTaskWindows.add(new TaskWindowWrapper(answerPlaceholder, twStart, twEnd)); } @@ -63,7 +64,7 @@ public abstract class CCDocumentListener extends DocumentAdapter { if (useLength()) { answerPlaceholder.setLength(length); } else { - answerPlaceholder.setReplacementLength(length); + answerPlaceholder.setPossibleAnswer(document.getText(TextRange.create(start, start + length ))); } } } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java index ad6b44392375..eb9445ab2896 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCEditorFactoryListener.java @@ -12,10 +12,8 @@ import com.intellij.openapi.editor.event.EditorFactoryListener; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; -import com.jetbrains.edu.coursecreator.format.TaskFile; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.TaskFile; import org.jetbrains.annotations.NotNull; public class CCEditorFactoryListener implements EditorFactoryListener { @@ -30,7 +28,8 @@ public class CCEditorFactoryListener implements EditorFactoryListener { if (virtualFile == null) { return; } - Course course = CCProjectService.getInstance(project).getCourse(); + final CCProjectService service = CCProjectService.getInstance(project); + Course course = service.getCourse(); if (course == null) { return; } @@ -40,9 +39,7 @@ public class CCEditorFactoryListener implements EditorFactoryListener { } final VirtualFile lessonDir = taskDir.getParent(); if (lessonDir == null) return; - final Lesson lesson = course.getLesson(lessonDir.getName()); - final Task task = lesson.getTask(taskDir.getName()); - final TaskFile taskFile = task.getTaskFile(virtualFile.getName()); + final TaskFile taskFile = service.getTaskFile(virtualFile); if (taskFile == null) { return; } @@ -51,9 +48,9 @@ public class CCEditorFactoryListener implements EditorFactoryListener { editor.getDocument().addDocumentListener(listener); EditorActionManager.getInstance() .setReadonlyFragmentModificationHandler(editor.getDocument(), new TaskWindowDeleteHandler(editor)); - CCProjectService.getInstance(project).drawTaskWindows(virtualFile, editor); + service.drawTaskWindows(virtualFile, editor); editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null); - taskFile.createGuardedBlocks(editor); + CCAnswerPlaceholderPainter.createGuardedBlocks(editor, taskFile); } @Override diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java index e4c44a97e62f..710843b57967 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectComponent.java @@ -16,11 +16,11 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileAdapter; import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.VirtualFileManager; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.coursecreator.actions.CCRunTestsAction; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; -import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -115,10 +115,10 @@ public class CCProjectComponent implements ProjectComponent { } VirtualFile removedFile = event.getFile(); if (removedFile.getName().contains(".answer")) { - deleteTaskFile(course, removedFile); + deleteTaskFile(removedFile); } if (removedFile.getName().contains("task")) { - deleteTask(course, removedFile); + deleteTask(removedFile); } if (removedFile.getName().contains("lesson")) { deleteLesson(course, removedFile); @@ -130,15 +130,17 @@ public class CCProjectComponent implements ProjectComponent { if (!courseDir.getName().equals(myProject.getName())) { return; } - Lesson lesson = course.getLesson(file.getName()); + final CCProjectService projectService = CCProjectService.getInstance(myProject); + Lesson lesson = projectService.getLesson(file.getName()); if (lesson != null) { course.getLessons().remove(lesson); - course.getLessonsMap().remove(file.getName()); + projectService.getLessonsMap().remove(file.getName()); } } - private void deleteTask(Course course, VirtualFile removedFile) { + private void deleteTask(VirtualFile removedFile) { VirtualFile lessonDir = removedFile.getParent(); + final CCProjectService projectService = CCProjectService.getInstance(myProject); if (lessonDir == null || !lessonDir.getName().contains("lesson")) { return; } @@ -146,20 +148,20 @@ public class CCProjectComponent implements ProjectComponent { if (!courseDir.getName().equals(myProject.getName())) { return; } - Lesson lesson = course.getLesson(lessonDir.getName()); + Lesson lesson = projectService.getLesson(lessonDir.getName()); if (lesson == null) { return; } - Task task = lesson.getTask(removedFile.getName()); + Task task = projectService.getTask(removedFile.getPath()); if (task == null) { return; } lesson.getTaskList().remove(task); - lesson.getTasksMap().remove(removedFile.getName()); + projectService.getTasksMap().remove(removedFile.getPath()); } - private void deleteTaskFile(Course course, VirtualFile removedFile) { - + private void deleteTaskFile(VirtualFile removedFile) { + final CCProjectService projectService = CCProjectService.getInstance(myProject); final VirtualFile taskDir = removedFile.getParent(); if (taskDir == null || !taskDir.getName().contains("task")) { return; @@ -172,15 +174,15 @@ public class CCProjectComponent implements ProjectComponent { if (!courseDir.getName().equals(myProject.getName())) { return; } - Lesson lesson = course.getLesson(lessonDir.getName()); + Lesson lesson = projectService.getLesson(lessonDir.getName()); if (lesson == null) { return; } - Task task = lesson.getTask(taskDir.getName()); + Task task = projectService.getTask(taskDir.getPath()); if (task == null) { return; } - TaskFile taskFile = task.getTaskFile(removedFile.getName()); + TaskFile taskFile = projectService.getTaskFile(removedFile); if (taskFile == null) { return; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java index cbf3d1d118b9..2d950285b832 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCProjectService.java @@ -29,9 +29,9 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.util.xmlb.XmlSerializer; -import com.jetbrains.edu.coursecreator.format.*; -import org.jdom.Element; +import com.intellij.psi.PsiDirectory; +import com.intellij.util.xmlb.XmlSerializerUtil; +import com.jetbrains.edu.courseFormat.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,44 +46,51 @@ import java.util.Map; @Storage(file = "$PROJECT_CONFIG_DIR$/course_service.xml") } ) -public class CCProjectService implements PersistentStateComponent { - +public class CCProjectService implements PersistentStateComponent { private static final Logger LOG = Logger.getInstance(CCProjectService.class.getName()); private Course myCourse; - public static final String COURSE_ELEMENT = "course"; + + //directory name to Lesson + private Map myLessonsMap = new HashMap(); + + //directory path to Task + public Map myTasksMap = new HashMap(); + private static final Map myDocumentListeners = new HashMap(); - public void setCourse(@NotNull final Course course) { - myCourse = course; + public Map getLessonsMap() { + return myLessonsMap; } - public Course getCourse() { - return myCourse; + public void setLessonsMap(Map lessonsMap) { + myLessonsMap = lessonsMap; } - @Override - public Element getState() { - final Element el = new Element("CCProjectService"); - if (myCourse != null) { - Element courseElement = new Element(COURSE_ELEMENT); - XmlSerializer.serializeInto(myCourse, courseElement); - el.addContent(courseElement); - } - return el; + public Lesson getLesson(@NotNull final String name) { + return myLessonsMap.get(name); } - @Override - public void loadState(Element el) { - myCourse = XmlSerializer.deserialize(el.getChild(COURSE_ELEMENT), Course.class); - if (myCourse != null) { - myCourse.init(); - } + public void addLesson(@NotNull final Lesson lesson, @NotNull final PsiDirectory directory) { + myLessonsMap.put(directory.getName(), lesson); } - public static CCProjectService getInstance(@NotNull Project project) { - return ServiceManager.getService(project, CCProjectService.class); + public Map getTasksMap() { + return myTasksMap; } + public void setTasksMap(Map tasksMap) { + myTasksMap = tasksMap; + } + + public void addTask(@NotNull final Task task, PsiDirectory taskDirectory) { + myTasksMap.put(taskDirectory.getVirtualFile().getPath(), task); + } + + public Task getTask(@NotNull final String name) { + return myTasksMap.get(name); + } + + public static void deleteProjectFile(File file, @NotNull final Project project) { if (!file.delete()) { LOG.info("Failed to delete file " + file.getPath()); @@ -110,15 +117,16 @@ public class CCProjectService implements PersistentStateComponent { if (!lessonDirName.contains("lesson")) { return null; } - Lesson lesson = myCourse.getLessonsMap().get(lessonDirName); + Lesson lesson = myLessonsMap.get(lessonDirName); if (lesson == null) { return null; } - Task task = lesson.getTask(taskDirName); + Task task = getTask(taskDir.getPath()); if (task == null) { return null; } - return task.getTaskFile(virtualFile.getName()); + String fileName = getRealTaskFileName(virtualFile.getName()); + return task.getTaskFile(fileName); } public void drawTaskWindows(@NotNull final VirtualFile virtualFile, @NotNull final Editor editor) { @@ -128,7 +136,7 @@ public class CCProjectService implements PersistentStateComponent { } List answerPlaceholders = taskFile.getAnswerPlaceholders(); for (AnswerPlaceholder answerPlaceholder : answerPlaceholders) { - answerPlaceholder.drawHighlighter(editor, false); + CCAnswerPlaceholderPainter.drawHighlighter(answerPlaceholder, editor, false); } } @@ -185,6 +193,8 @@ public class CCProjectService implements PersistentStateComponent { } return Integer.parseInt(fullName.substring(logicalName.length())) - 1; } + + @Nullable public static String getRealTaskFileName(String name) { String nameWithoutExtension = FileUtil.getNameWithoutExtension(name); String extension = FileUtilRt.getExtension(name); @@ -207,4 +217,27 @@ public class CCProjectService implements PersistentStateComponent { CCUtils.enableAction(e, true); return true; } + + public Course getCourse() { + return myCourse; + } + + public void setCourse(@NotNull final Course course) { + myCourse = course; + } + + @Override + public CCProjectService getState() { + return this; + } + + @Override + public void loadState(CCProjectService state) { + XmlSerializerUtil.copyBean(state, this); + } + + public static CCProjectService getInstance(@NotNull Project project) { + return ServiceManager.getService(project, CCProjectService.class); + } + } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java index 50a4693d29cc..1f238337e108 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCRefactoringElementListenerProvider.java @@ -22,11 +22,11 @@ import com.intellij.psi.PsiFile; import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerProvider; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.coursecreator.actions.CCRunTestsAction; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; -import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,7 +64,8 @@ public class CCRefactoringElementListenerProvider implements RefactoringElementL private static void renameTaskFile(PsiFile file, String oldName) { final PsiDirectory taskDir = file.getContainingDirectory(); - Course course = CCProjectService.getInstance(file.getProject()).getCourse(); + final CCProjectService service = CCProjectService.getInstance(file.getProject()); + Course course = service.getCourse(); if (course == null) { return; } @@ -75,11 +76,11 @@ public class CCRefactoringElementListenerProvider implements RefactoringElementL if (lessonDir == null || !lessonDir.getName().contains("lesson")) { return; } - Lesson lesson = course.getLesson(lessonDir.getName()); + Lesson lesson = service.getLesson(lessonDir.getName()); if (lesson == null) { return; } - Task task = lesson.getTask(taskDir.getName()); + Task task = service.getTask(taskDir.getVirtualFile().getPath()); if (task == null) { return; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index f5ca9378eebf..059e56b2a81d 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -13,7 +13,7 @@ import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.vfs.VirtualFile; -import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.courseFormat.Course; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java similarity index 78% rename from python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java rename to python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java index 6e9b78920591..406fbe69cda8 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddTaskWindow.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java @@ -13,17 +13,21 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; +import com.jetbrains.edu.coursecreator.CCAnswerPlaceholderPainter; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.*; import com.jetbrains.edu.coursecreator.ui.CreateTaskWindowDialog; import org.jetbrains.annotations.NotNull; import java.util.List; -public class CCAddTaskWindow extends DumbAwareAction { - private static final Logger LOG = Logger.getInstance(CCAddTaskWindow.class); +public class CCAddAnswerPlaceholder extends DumbAwareAction { + private static final Logger LOG = Logger.getInstance(CCAddAnswerPlaceholder.class); - public CCAddTaskWindow() { + public CCAddAnswerPlaceholder() { super("Add Answer Placeholder", "Add answer placeholder", null); } @@ -32,7 +36,7 @@ public class CCAddTaskWindow extends DumbAwareAction { List answerPlaceholders = taskFile.getAnswerPlaceholders(); for (AnswerPlaceholder existingAnswerPlaceholder : answerPlaceholders) { int twStart = existingAnswerPlaceholder.getRealStartOffset(document); - int twEnd = existingAnswerPlaceholder.getReplacementLength() + twStart; + int twEnd = existingAnswerPlaceholder.getPossibleAnswerLength() + twStart; if ((start >= twStart && start < twEnd) || (end > twStart && end <= twEnd) || (twStart >= start && twStart < end) || (twEnd > start && twEnd <= end)) { return true; @@ -57,25 +61,27 @@ public class CCAddTaskWindow extends DumbAwareAction { final int start = model.getSelectionStart(); final int end = model.getSelectionEnd(); final int lineNumber = document.getLineNumber(start); - final int length = end - start; int realStart = start - document.getLineStartOffset(lineNumber); final CCProjectService service = CCProjectService.getInstance(project); - final Course course = service.getCourse(); final PsiDirectory taskDir = file.getContainingDirectory(); final PsiDirectory lessonDir = taskDir.getParent(); if (lessonDir == null) return; - final Lesson lesson = course.getLesson(lessonDir.getName()); - final Task task = lesson.getTask(taskDir.getName()); - final TaskFile taskFile = task.getTaskFile(file.getName()); + final Lesson lesson = service.getLesson(lessonDir.getName()); + final Task task = service.getTask(taskDir.getVirtualFile().getPath()); + final TaskFile taskFile = service.getTaskFile(file.getVirtualFile()); if (taskFile == null) { return; } if (areTaskWindowsIntersect(taskFile, document, start, end)) { return; } - final AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder(lineNumber, realStart, length, model.getSelectedText()); + final AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder(); + answerPlaceholder.setLine(lineNumber); + answerPlaceholder.setStart(realStart); + answerPlaceholder.setPossibleAnswer(model.getSelectedText()); + CreateTaskWindowDialog dlg = new CreateTaskWindowDialog(project, answerPlaceholder, lesson.getIndex(), task.getIndex(), file.getVirtualFile().getNameWithoutExtension(), taskFile.getAnswerPlaceholders().size() + 1); @@ -84,10 +90,11 @@ public class CCAddTaskWindow extends DumbAwareAction { return; } int index = taskFile.getAnswerPlaceholders().size() + 1; - taskFile.addTaskWindow(answerPlaceholder, index); - taskFile.sortTaskWindows(); - answerPlaceholder.drawHighlighter(editor, false); - answerPlaceholder.createGuardedBlocks(editor); + answerPlaceholder.setIndex(index); + taskFile.addAnswerPlaceholder(answerPlaceholder); + //taskFile.sortTaskWindows(); + CCAnswerPlaceholderPainter.drawHighlighter(answerPlaceholder, editor, false); + CCAnswerPlaceholderPainter.createGuardedBlocks(editor, answerPlaceholder); } @Override @@ -119,24 +126,23 @@ public class CCAddTaskWindow extends DumbAwareAction { int end = selectionModel.getSelectionEnd(); final CCProjectService service = CCProjectService.getInstance(project); - final Course course = service.getCourse(); final PsiDirectory taskDir = file.getContainingDirectory(); final PsiDirectory lessonDir = taskDir.getParent(); if (lessonDir == null) return; - final Lesson lesson = course.getLesson(lessonDir.getName()); + final Lesson lesson = service.getLesson(lessonDir.getName()); if (lesson == null) { presentation.setVisible(false); presentation.setEnabled(false); return; } - final Task task = lesson.getTask(taskDir.getName()); + final Task task = service.getTask(taskDir.getVirtualFile().getPath()); if (task == null) { presentation.setVisible(false); presentation.setEnabled(false); return; } - TaskFile taskFile = task.getTaskFile(file.getName()); + TaskFile taskFile = service.getTaskFile(file.getVirtualFile()); if (taskFile == null) { LOG.info("could not find task file"); presentation.setVisible(false); diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java index 81ee890989bb..1625f6361c16 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java @@ -11,8 +11,8 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiDirectory; +import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.Course; import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java index 1857f9d75c3a..0c6fbe30320b 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java @@ -16,19 +16,19 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.util.io.ZipUtil; +import com.jetbrains.edu.courseFormat.*; import com.jetbrains.edu.coursecreator.CCDocumentListener; +import com.jetbrains.edu.coursecreator.CCLanguageManager; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.CCLanguageManager; -import com.jetbrains.edu.coursecreator.format.*; import com.jetbrains.edu.coursecreator.ui.CreateCourseArchiveDialog; import org.jetbrains.annotations.NotNull; import java.io.*; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.zip.ZipOutputStream; @@ -74,28 +74,24 @@ public class CCCreateCourseArchive extends DumbAwareAction { return; } final VirtualFile baseDir = project.getBaseDir(); - final Map lessons = course.getLessonsMap(); + final Map lessons = service.getLessonsMap(); //map to store initial task file final Map taskFiles = new HashMap(); - for (Map.Entry lesson : lessons.entrySet()) { - final VirtualFile lessonDir = baseDir.findChild(lesson.getKey()); - if (lessonDir == null) continue; - for (Map.Entry task : lesson.getValue().myTasksMap.entrySet()) { - final VirtualFile taskDir = lessonDir.findChild(task.getKey()); - if (taskDir == null) continue; - for (final Map.Entry entry : task.getValue().task_files.entrySet()) { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - createUserFile(project, taskFiles, taskDir, taskDir, entry); - } - }); - } + + for (Map.Entry task : service.getTasksMap().entrySet()) { + final VirtualFile taskDir = LocalFileSystem.getInstance().findFileByPath(task.getKey()); + if (taskDir == null) continue; + for (final Map.Entry entry : task.getValue().getTaskFiles().entrySet()) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + createUserFile(project, taskFiles, taskDir, taskDir, entry); + } + }); } } generateJson(project); packCourse(baseDir, lessons, course); - resetTaskFiles(taskFiles); synchronize(project); } @@ -136,9 +132,9 @@ public class CCCreateCourseArchive extends DumbAwareAction { if (document == null) return; final TaskFile taskFile = taskFiles.getValue(); TaskFile taskFileSaved = new TaskFile(); - taskFile.copy(taskFileSaved); + TaskFile.copy(taskFile, taskFileSaved); for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { - answerPlaceholder.setLength(answerPlaceholder.getReplacementLength()); + answerPlaceholder.setLength(answerPlaceholder.getPossibleAnswerLength()); } CommandProcessor.getInstance().executeCommand(project, new Runnable() { @Override @@ -154,7 +150,7 @@ public class CCCreateCourseArchive extends DumbAwareAction { InsertionListener listener = new InsertionListener(taskFile); document.addDocumentListener(listener); taskFilesCopy.put(taskFile, taskFileSaved); - Collections.sort(taskFile.getAnswerPlaceholders()); + //Collections.sort(taskFile.getAnswerPlaceholders()); for (int i = taskFile.getAnswerPlaceholders().size() - 1; i >= 0; i--) { final AnswerPlaceholder answerPlaceholder = taskFile.getAnswerPlaceholders().get(i); replaceTaskWindow(project, document, answerPlaceholder); @@ -198,14 +194,6 @@ public class CCCreateCourseArchive extends DumbAwareAction { ProjectView.getInstance(project).refresh(); } - public static void resetTaskFiles(@NotNull final Map taskFiles) { - for (Map.Entry entry : taskFiles.entrySet()) { - TaskFile realTaskFile = entry.getKey(); - TaskFile savedTaskFile = entry.getValue(); - realTaskFile.update(savedTaskFile); - } - } - private void packCourse(@NotNull final VirtualFile baseDir, @NotNull final Map lessons, @NotNull final Course course) { try { File zipFile = new File(myLocationDir, myZipName + ".zip"); diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java index 0866d4e206c4..0489c0104880 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateLesson.java @@ -13,11 +13,12 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiManager; import com.intellij.util.PlatformIcons; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -49,11 +50,11 @@ public class CCCreateLesson extends DumbAwareAction { //"Create Lesson" invoked from project root creates new lesson as last lesson if (directory.getVirtualFile().equals(project.getBaseDir())) { final int size = course.getLessons().size(); - createLesson(directory, size + 1, view, course); + createLesson(project, size + 1, view, course); return; } //"Create Lesson" invoked from any of lesson directories creates new lesson as next lesson - Lesson lesson = course.getLesson(directory.getName()); + Lesson lesson = service.getLesson(directory.getName()); if (lesson != null) { int index = lesson.getIndex(); List lessons = course.getLessons(); @@ -65,12 +66,11 @@ public class CCCreateLesson extends DumbAwareAction { if (parent == null) { return; } - createLesson(parent, index + 1, view, course); - course.init(); + createLesson(project, index + 1, view, course); } } - private static void createLesson(@NotNull final PsiDirectory projectDir, + private static void createLesson(@NotNull final Project project, final int index, final IdeView view, @NotNull final Course course) { @@ -81,7 +81,7 @@ public class CCCreateLesson extends DumbAwareAction { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - createLessonDir(projectDir, index, lessonName, view, course); + createLessonDir(project, index, lessonName, view, course); } }); } @@ -91,7 +91,8 @@ public class CCCreateLesson extends DumbAwareAction { if (lessonDir == null) { return; } - Lesson l = course.getLesson(lessonDir.getName()); + final CCProjectService service = CCProjectService.getInstance(project); + Lesson l = service.getLesson(lessonDir.getName()); if (l == null) { return; } @@ -108,21 +109,24 @@ public class CCCreateLesson extends DumbAwareAction { } } }); - course.getLessonsMap().put(lessonDir.getName(), l); + service.getLessonsMap().put(lessonDir.getName(), l); } @Nullable - public static PsiDirectory createLessonDir(@NotNull final PsiDirectory projectDir, int index, String name, final IdeView view, + public static PsiDirectory createLessonDir(@NotNull final Project project, int index, String name, final IdeView view, @NotNull final Course course) { String lessonFolderName = "lesson" + index; + final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(project.getBaseDir()); final PsiDirectory lessonDirectory = DirectoryUtil.createSubdirectories("lesson" + index, projectDir, "\\/"); + final CCProjectService service = CCProjectService.getInstance(project); if (lessonDirectory != null) { if (view != null) { view.selectElement(lessonDirectory); } - final Lesson lesson = new Lesson(name != null ? name : lessonFolderName); + final Lesson lesson = new Lesson(); + lesson.setName(name != null ? name : lessonFolderName); lesson.setIndex(index); - course.addLesson(lesson, lessonDirectory); + service.addLesson(lesson, lessonDirectory); } return lessonDirectory; } @@ -148,8 +152,9 @@ public class CCCreateLesson extends DumbAwareAction { CCUtils.enableAction(event, true); return; } - Course course = CCProjectService.getInstance(project).getCourse(); - if (directory != null && course != null && course.getLesson(directory.getName()) != null) { + final CCProjectService service = CCProjectService.getInstance(project); + Course course = service.getCourse(); + if (directory != null && course != null && service.getLesson(directory.getName()) != null) { CCUtils.enableAction(event, true); return; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java index 85b2a6d5b19d..b6f17573197b 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTask.java @@ -22,12 +22,12 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.util.PlatformIcons; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.coursecreator.CCLanguageManager; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -55,7 +55,7 @@ public class CCCreateTask extends DumbAwareAction { public static void createTask(final IdeView view, final Project project, final PsiDirectory lessonDir, boolean showDialog) { final CCProjectService service = CCProjectService.getInstance(project); final Course course = service.getCourse(); - final Lesson lesson = course.getLesson(lessonDir.getName()); + final Lesson lesson = service.getLesson(lessonDir.getName()); final int size = lesson.getTaskList().size(); final String taskName; if (showDialog) { @@ -81,7 +81,8 @@ public class CCCreateTask extends DumbAwareAction { CCUtils.markDirAsSourceRoot(taskDirectory.getVirtualFile(), project); final Task task = new Task(taskName); task.setIndex(size + 1); - lesson.addTask(task, taskDirectory); + service.addTask(task, taskDirectory); + lesson.addTask(task); createFromTemplateAndOpen(taskDirectory, manager.getTestsTemplate(project), view); createFromTemplateAndOpen(taskDirectory, FileTemplateManager.getInstance(project).getInternalTemplate("task.html"), view); @@ -157,7 +158,7 @@ public class CCCreateTask extends DumbAwareAction { final PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view); final CCProjectService service = CCProjectService.getInstance(project); final Course course = service.getCourse(); - if (course != null && directory != null && course.getLesson(directory.getName()) == null) { + if (course != null && directory != null && service.getLesson(directory.getName()) == null) { presentation.setVisible(false); presentation.setEnabled(false); return; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java index 5483b1ef8eaa..58e9474000ce 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateTaskFile.java @@ -19,12 +19,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.coursecreator.CCLanguageManager; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.CCLanguageManager; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; import com.jetbrains.edu.coursecreator.ui.CreateTaskFileDialog; import org.jetbrains.annotations.NotNull; @@ -52,8 +51,7 @@ public class CCCreateTaskFile extends DumbAwareAction { } final CCProjectService service = CCProjectService.getInstance(project); final Course course = service.getCourse(); - final Lesson lesson = course.getLesson(lessonDir.getName()); - final Task task = lesson.getTask(taskDir.getName()); + final Task task = service.getTask(taskDir.getVirtualFile().getPath()); final int index = task.getTaskFiles().size() + 1; String generatedName = "file" + index; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java index 0880006095b9..b5ca452f53a1 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteTaskWindow.java @@ -1,21 +1,19 @@ package com.jetbrains.edu.coursecreator.actions; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.TaskFile; +import com.jetbrains.edu.coursecreator.CCAnswerPlaceholderPainter; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.AnswerPlaceholder; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; import java.util.List; public class CCDeleteTaskWindow extends CCTaskWindowAction { - private static final Logger LOG = Logger.getInstance(CCDeleteTaskWindow.class); public CCDeleteTaskWindow() { super("Delete Answer Placeholder","Delete answer placeholder", null); @@ -27,18 +25,15 @@ public class CCDeleteTaskWindow extends CCTaskWindowAction { PsiFile psiFile = state.getFile(); final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile); if (document == null) return; - final CCProjectService service = CCProjectService.getInstance(project); - final Course course = service.getCourse(); TaskFile taskFile = state.getTaskFile(); AnswerPlaceholder answerPlaceholder = state.getAnswerPlaceholder(); final List answerPlaceholders = taskFile.getAnswerPlaceholders(); if (answerPlaceholders.contains(answerPlaceholder)) { - answerPlaceholder.removeResources(project); answerPlaceholders.remove(answerPlaceholder); final Editor editor = state.getEditor(); editor.getMarkupModel().removeAllHighlighters(); CCProjectService.getInstance(project).drawTaskWindows(psiFile.getVirtualFile(), editor); - taskFile.createGuardedBlocks(editor); + CCAnswerPlaceholderPainter.createGuardedBlocks(editor, taskFile); } } } \ No newline at end of file diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java index 62212389b8d5..e96bc902e70f 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRename.java @@ -26,8 +26,8 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.Course; import org.jetbrains.annotations.NotNull; import javax.swing.*; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java index eaea9bf7e0ad..fc8d819fb2a0 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameLesson.java @@ -18,8 +18,9 @@ package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.coursecreator.CCProjectService; public class CCRenameLesson extends CCRename { @@ -34,7 +35,7 @@ public class CCRenameLesson extends CCRename { @Override public boolean processRename(Project project, PsiDirectory directory, Course course) { - Lesson lesson = course.getLesson(directory.getName()); + Lesson lesson = CCProjectService.getInstance(project).getLesson(directory.getName()); if (lesson == null) { return false; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java index 4690d0d1993f..40d99f7392c3 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRenameTask.java @@ -18,9 +18,10 @@ package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiDirectory; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.coursecreator.CCProjectService; public class CCRenameTask extends CCRename { public CCRenameTask() { @@ -38,11 +39,12 @@ public class CCRenameTask extends CCRename { if (lessonDir == null || !lessonDir.getName().contains("lesson")) { return false; } - Lesson lesson = course.getLesson(lessonDir.getName()); + final CCProjectService service = CCProjectService.getInstance(project); + Lesson lesson = service.getLesson(lessonDir.getName()); if (lesson == null) { return false; } - Task task = lesson.getTask(directory.getName()); + Task task = service.getTask(directory.getVirtualFile().getPath()); if (task == null) { return false; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java index f20ca9ab1aad..251cd167eb9e 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCRunTestsAction.java @@ -34,12 +34,11 @@ import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.containers.HashMap; +import com.jetbrains.edu.courseFormat.*; +import com.jetbrains.edu.coursecreator.CCLanguageManager; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.CCLanguageManager; -import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.FileOutputStream; import java.io.IOException; @@ -79,15 +78,15 @@ public abstract class CCRunTestsAction extends AnAction { final PsiDirectory lessonDir = taskDir.getParent(); if (lessonDir == null) return; if (course == null) return; - final Lesson lesson = course.getLesson(lessonDir.getName()); + final Lesson lesson = service.getLesson(lessonDir.getName()); if (lesson == null) return; - final Task task = lesson.getTask(taskDir.getName()); + final Task task = service.getTask(taskDir.getVirtualFile().getPath()); if (task == null) { presentation.setVisible(false); presentation.setEnabled(false); return; } - TaskFile taskFile = task.getTaskFile(psiFile.getName()); + TaskFile taskFile = service.getTaskFile(psiFile.getVirtualFile()); if (taskFile == null) { LOG.info("could not find task file"); presentation.setVisible(false); @@ -126,7 +125,7 @@ public abstract class CCRunTestsAction extends AnAction { if (taskDir == null) { return; } - final Task task = getTask(course, taskDir); + final Task task = CCProjectService.getInstance(project).getTask(taskDir.getPath()); if (task == null) { return; } @@ -208,23 +207,6 @@ public abstract class CCRunTestsAction extends AnAction { @NotNull final VirtualFile taskDir, @NotNull final VirtualFile testFile); - @Nullable - private static Task getTask(@NotNull final Course course, @NotNull final VirtualFile taskDir) { - if (!taskDir.getName().contains("task")) { - return null; - } - VirtualFile lessonDir = taskDir.getParent(); - if (lessonDir == null || !lessonDir.getName().contains("lesson")) { - return null; - } - Lesson lesson = course.getLesson(lessonDir.getName()); - if (lesson == null) { - return null; - } - return lesson.getTask(taskDir.getName()); - } - - //some tests could compare task files after user modifications with initial task files private static void createResourceFiles(@NotNull final VirtualFile file, @NotNull final Project project) { VirtualFile taskDir = file.getParent(); @@ -248,7 +230,6 @@ public abstract class CCRunTestsAction extends AnAction { HashMap taskFilesCopy = new HashMap(); for (Map.Entry entry : task.getTaskFiles().entrySet()) { CCCreateCourseArchive.createUserFile(project, taskFilesCopy, taskResourceDir, taskDir, entry); - CCCreateCourseArchive.resetTaskFiles(taskFilesCopy); } } } @@ -282,7 +263,7 @@ public abstract class CCRunTestsAction extends AnAction { printWriter = new PrintWriter(new FileOutputStream(windowsFile.getPath())); for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { int start = answerPlaceholder.getRealStartOffset(document); - String windowDescription = document.getText(new TextRange(start, start + answerPlaceholder.getReplacementLength())); + String windowDescription = document.getText(new TextRange(start, start + answerPlaceholder.getPossibleAnswerLength())); printWriter.println("#educational_plugin_window = " + windowDescription); } ApplicationManager.getApplication().runWriteAction(new Runnable() { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java index a62134edd196..d61cbcb99f0a 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowPreview.java @@ -33,8 +33,12 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; +import com.jetbrains.edu.coursecreator.CCAnswerPlaceholderPainter; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.*; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -84,13 +88,13 @@ public class CCShowPreview extends DumbAwareAction { if (lessonDir == null) { return; } - Course course = CCProjectService.getInstance(project).getCourse(); + final CCProjectService service = CCProjectService.getInstance(project); + Course course = service.getCourse(); if (course == null) { return; } - Lesson lesson = course.getLesson(lessonDir.getName()); - Task task = lesson.getTask(taskDir.getName()); - TaskFile taskFile = task.getTaskFile(file.getName()); + Task task = service.getTask(taskDir.getVirtualFile().getPath()); + TaskFile taskFile = service.getTaskFile(file.getVirtualFile()); if (taskFile == null) { return; } @@ -129,7 +133,7 @@ public class CCShowPreview extends DumbAwareAction { } }); for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) { - answerPlaceholder.drawHighlighter(createdEditor, true); + CCAnswerPlaceholderPainter.drawHighlighter(answerPlaceholder, createdEditor, true); } JPanel header = new JPanel(); header.setLayout(new BoxLayout(header, BoxLayout.Y_AXIS)); @@ -142,6 +146,5 @@ public class CCShowPreview extends DumbAwareAction { createdEditor.setCaretEnabled(false); showPreviewFrame.setComponent(labeledEditor); showPreviewFrame.show(); - CCCreateCourseArchive.resetTaskFiles(taskFilesCopy); } } \ No newline at end of file diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java index 73336433d016..b4c955091d05 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCShowTaskWindowDetails.java @@ -3,8 +3,11 @@ package com.jetbrains.edu.coursecreator.actions; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.*; import com.jetbrains.edu.coursecreator.ui.CreateTaskWindowDialog; import org.jetbrains.annotations.NotNull; @@ -18,13 +21,12 @@ public class CCShowTaskWindowDetails extends CCTaskWindowAction { protected void performTaskWindowAction(@NotNull CCState state) { final Project project = state.getProject(); final CCProjectService service = CCProjectService.getInstance(project); - final Course course = service.getCourse(); PsiFile file = state.getFile(); final PsiDirectory taskDir = file.getContainingDirectory(); final PsiDirectory lessonDir = taskDir.getParent(); if (lessonDir == null) return; - final Lesson lesson = course.getLesson(lessonDir.getName()); - final Task task = lesson.getTask(taskDir.getName()); + final Lesson lesson = service.getLesson(lessonDir.getName()); + final Task task = service.getTask(taskDir.getVirtualFile().getPath()); final TaskFile taskFile = state.getTaskFile(); AnswerPlaceholder answerPlaceholder = state.getAnswerPlaceholder(); CreateTaskWindowDialog dlg = new CreateTaskWindowDialog(project, answerPlaceholder, lesson.getIndex(), task.getIndex(), diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java index 1334a743d389..a01c56a2c1a8 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCTaskWindowAction.java @@ -8,9 +8,9 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.AnswerPlaceholder; -import com.jetbrains.edu.coursecreator.format.TaskFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java index 4e861a8ea33a..2f6a628711fb 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCDirectoryNode.java @@ -6,11 +6,11 @@ import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDirectory; import com.intellij.ui.SimpleTextAttributes; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.coursecreator.CCProjectService; import com.jetbrains.edu.coursecreator.CCUtils; -import com.jetbrains.edu.coursecreator.format.Course; -import com.jetbrains.edu.coursecreator.format.Lesson; -import com.jetbrains.edu.coursecreator.format.Task; import org.jetbrains.annotations.NotNull; public class CCDirectoryNode extends PsiDirectoryNode { @@ -30,7 +30,8 @@ public class CCDirectoryNode extends PsiDirectoryNode { //TODO:change presentable name for files with suffix _answer String valueName = myValue.getName(); - final Course course = CCProjectService.getInstance(myProject).getCourse(); + final CCProjectService service = CCProjectService.getInstance(myProject); + final Course course = service.getCourse(); if (course == null) return; if (myProject.getBaseDir().equals(myValue.getVirtualFile())) { data.clearText(); @@ -38,7 +39,7 @@ public class CCDirectoryNode extends PsiDirectoryNode { data.addText(" (" + course.getName() + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES); return; } - final Lesson lesson = course.getLesson(valueName); + final Lesson lesson = service.getLesson(valueName); if (lesson != null) { data.clearText(); data.addText(valueName, SimpleTextAttributes.REGULAR_ATTRIBUTES); @@ -48,13 +49,13 @@ public class CCDirectoryNode extends PsiDirectoryNode { else { final PsiDirectory parentDir = myValue.getParentDirectory(); if (parentDir != null) { - final Lesson parentLesson = course.getLesson(parentDir.getName()); + final Lesson parentLesson = service.getLesson(parentDir.getName()); if (parentLesson != null) { - final Task task = parentLesson.getTask(valueName); + final Task task = service.getTask(myValue.getVirtualFile().getPath()); if (task != null) { data.clearText(); data.addText(valueName, SimpleTextAttributes.REGULAR_ATTRIBUTES); - data.addText(" (" + task.name + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES); + data.addText(" (" + task.getName() + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES); return; } } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java index 9f3afb1b32c0..4b496ec6c1cf 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskFileDialog.java @@ -8,9 +8,9 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.ui.DoubleClickListener; import com.intellij.ui.ListScrollingUtil; import com.intellij.ui.components.JBList; -import com.jetbrains.edu.coursecreator.CCUtils; +import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.coursecreator.CCLanguageManager; -import com.jetbrains.edu.coursecreator.format.Course; +import com.jetbrains.edu.coursecreator.CCUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java index c7efd81baf72..858b0e933040 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowDialog.java @@ -1,25 +1,18 @@ package com.jetbrains.edu.coursecreator.ui; -import com.intellij.ide.projectView.ProjectView; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.ValidationInfo; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; -import com.jetbrains.edu.coursecreator.CCProjectService; -import com.jetbrains.edu.coursecreator.format.AnswerPlaceholder; +import com.jetbrains.edu.courseFormat.AnswerPlaceholder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.io.*; public class CreateTaskWindowDialog extends DialogWrapper { private static final String ourTitle = "Add Answer Placeholder"; - private static final Logger LOG = Logger.getInstance(CreateTaskWindowDialog.class.getName()); private final AnswerPlaceholder myAnswerPlaceholder; private final CreateTaskWindowPanel myPanel; private final Project myProject; @@ -36,124 +29,35 @@ public class CreateTaskWindowDialog extends DialogWrapper { myPanel = new CreateTaskWindowPanel(this); String generatedHintName = "lesson" + lessonIndex + "task" + taskIndex + taskFileName + "_" + taskWindowIndex; myPanel.setGeneratedHintName(generatedHintName); - if (answerPlaceholder.getHintName() != null) { - setHintText(project, answerPlaceholder); + if (answerPlaceholder.getHint() != null) { + setHintText(answerPlaceholder); } myProject = project; String taskWindowTaskText = answerPlaceholder.getTaskText(); myPanel.setTaskWindowText(taskWindowTaskText != null ? taskWindowTaskText : ""); - String hintName = answerPlaceholder.getHintName(); - myPanel.setHintName(hintName != null ? hintName : ""); + String hintName = answerPlaceholder.getHint(); + myPanel.setHintText(hintName != null ? hintName : ""); init(); initValidation(); } @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - private void setHintText(Project project, AnswerPlaceholder answerPlaceholder) { - VirtualFile hints = project.getBaseDir().findChild("hints"); - if (hints != null) { - File file = new File(hints.getPath(), answerPlaceholder.getHintName()); - StringBuilder hintText = new StringBuilder(); - if (file.exists()) { - BufferedReader bufferedReader = null; - try { - bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); - String line; - while ((line = bufferedReader.readLine()) != null) { - hintText.append(line).append("\n"); - } - myPanel.doClick(); - //myPanel.enableHint(true); - myPanel.setHintText(hintText.toString()); - } - catch (FileNotFoundException e) { - LOG.error("created hint was not found", e); - } - catch (IOException e) { - LOG.error(e); - } - finally { - if (bufferedReader != null) { - try { - bufferedReader.close(); - } - catch (IOException e) { - //close silently - } - } - } - } - } + private void setHintText(AnswerPlaceholder answerPlaceholder) { + String hintText = answerPlaceholder.getHint(); + + myPanel.doClick(); + myPanel.setHintText(hintText); } @Override protected void doOKAction() { String taskWindowText = myPanel.getAnswerPlaceholderText(); myAnswerPlaceholder.setTaskText(StringUtil.notNullize(taskWindowText)); - if (myPanel.createHint()) { - String hintName = myPanel.getHintName(); - myAnswerPlaceholder.setHint(hintName); - String hintText = myPanel.getHintText(); - createHint(hintName, hintText); - } else { - if (myAnswerPlaceholder.getHintName() != null) { - deleteHint(); - } - } + myAnswerPlaceholder.setLength(StringUtil.notNullize(taskWindowText).length()); + myAnswerPlaceholder.setHint(myPanel.getHintText()); super.doOKAction(); } - @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") - private void createHint(String hintName, String hintText) { - VirtualFile hintsDir = myProject.getBaseDir().findChild("hints"); - if (hintsDir != null) { - File hintFile = new File(hintsDir.getPath(), hintName); - OutputStreamWriter outputStreamWriter = null; - try { - outputStreamWriter = new OutputStreamWriter(new FileOutputStream(hintFile), "UTF-8"); - outputStreamWriter.write(hintText); - } - catch (FileNotFoundException e) { - //TODO:show error in UI - return; - } - catch (UnsupportedEncodingException e) { - LOG.error(e); - } - catch (IOException e) { - LOG.error(e); - } - finally { - if (outputStreamWriter != null) { - try { - outputStreamWriter.close(); - } - catch (IOException e) { - //close silently - } - } - } - } - VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); - ProjectView.getInstance(myProject).refresh(); - } - - private void deleteHint() { - VirtualFile hintsDir = myProject.getBaseDir().findChild("hints"); - if (hintsDir != null) { - String hintName = myAnswerPlaceholder.getHintName(); - if (hintName == null) { - return; - } - File hintFile = new File(hintsDir.getPath(), hintName); - if (hintFile.exists()) { - CCProjectService.deleteProjectFile(hintFile, myProject); - myAnswerPlaceholder.setHint(null); - myPanel.resetHint(); - } - } - } - @Nullable @Override protected JComponent createCenterPanel() { @@ -163,20 +67,7 @@ public class CreateTaskWindowDialog extends DialogWrapper { @Nullable @Override public ValidationInfo doValidate() { - String name = myPanel.getHintName(); - VirtualFile hintsDir = myProject.getBaseDir().findChild("hints"); - if (hintsDir == null) { - return null; - } - VirtualFile child = hintsDir.findChild(name); - if (child == null) { - return null; - } - return myAnswerPlaceholder.getHintName() != null ? null : new ValidationInfo("Hint file with such filename already exists"); - } - - public void validateInput() { - super.initValidation(); + return myAnswerPlaceholder.getHint() != null ? null : new ValidationInfo("Type hint"); } @Nullable diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form index 182dd58629e8..4de02982ef9a 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.form @@ -1,9 +1,9 @@
- + - + @@ -16,29 +16,9 @@ - - - - - - - - - - - - - - - - - - - - - + @@ -48,7 +28,7 @@ - + diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java index 96c6b9288379..5bfda1b3a044 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CreateTaskWindowPanel.java @@ -1,9 +1,6 @@ package com.jetbrains.edu.coursecreator.ui; -import com.intellij.ui.DocumentAdapter; - import javax.swing.*; -import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; @@ -12,10 +9,8 @@ public class CreateTaskWindowPanel extends JPanel { private final CreateTaskWindowDialog myDialog; private JPanel myPanel; - private JTextField myHintName; private JTextArea myHintText; private JCheckBox myCreateHintCheckBox; - private JLabel myHintNameLabel; private JLabel myHintTextLabel; private JTextField myTaskWindowText; private String myGeneratedHintName = ""; @@ -38,30 +33,17 @@ public class CreateTaskWindowPanel extends JPanel { }); myTaskWindowText.grabFocus(); - myHintName.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - myDialog.validateInput(); - } - }); } private void enableHint(boolean isEnable) { - myHintName.setEnabled(isEnable); myHintText.setEnabled(isEnable); - myHintNameLabel.setEnabled(isEnable); myHintTextLabel.setEnabled(isEnable); - myHintName.setText(myGeneratedHintName); } public void setTaskWindowText(String taskWindowText) { myTaskWindowText.setText(taskWindowText); } - public void setHintName(String hintName) { - myHintName.setText(hintName); - } - public void setHintText(String hintText) { myHintText.setText(hintText); } @@ -70,24 +52,15 @@ public class CreateTaskWindowPanel extends JPanel { return myTaskWindowText.getText(); } - public String getHintName() { - return myHintName.getText(); - } - public String getHintText() { return myHintText.getText(); } - public boolean createHint() { - return myHintName.isEnabled(); - } - public void doClick() { myCreateHintCheckBox.doClick(); } public void resetHint() { - myHintName.setText(""); myHintText.setText(""); } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java index 185edb35df41..3ca1671cec19 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java @@ -12,7 +12,6 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -159,7 +158,7 @@ public class StudyGenerator { for (AnswerPlaceholder answerPlaceholder : answerPlaceholders) { initAnswerPlaceholder(answerPlaceholder, taskFile, isRestarted); } - Collections.sort(answerPlaceholders); + //Collections.sort(answerPlaceholders); for (int i = 0; i < answerPlaceholders.size(); i++) { answerPlaceholders.get(i).setIndex(i); } diff --git a/python/educational/src/com/jetbrains/edu/courseFormat/AnswerPlaceholder.java b/python/educational/src/com/jetbrains/edu/courseFormat/AnswerPlaceholder.java index 49d04b840aef..b4f7af7f92db 100644 --- a/python/educational/src/com/jetbrains/edu/courseFormat/AnswerPlaceholder.java +++ b/python/educational/src/com/jetbrains/edu/courseFormat/AnswerPlaceholder.java @@ -5,12 +5,13 @@ import com.google.gson.annotations.SerializedName; import com.intellij.openapi.editor.Document; import com.intellij.util.xmlb.annotations.Transient; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Implementation of windows which user should type in */ -public class AnswerPlaceholder implements Comparable { +public class AnswerPlaceholder { @Expose private int line = 0; @Expose private int start = 0; @@ -61,7 +62,7 @@ public class AnswerPlaceholder implements Comparable { return hint; } - public void setHint(@NotNull final String hint) { + public void setHint(@Nullable final String hint) { this.hint = hint; } @@ -81,6 +82,14 @@ public class AnswerPlaceholder implements Comparable { myInitialState = initialState; } + public String getTaskText() { + return myTaskText; + } + + public void setTaskText(String taskText) { + myTaskText = taskText; + } + @Transient public TaskFile getTaskFile() { return myTaskFile; @@ -95,6 +104,10 @@ public class AnswerPlaceholder implements Comparable { return document.getLineStartOffset(line) + start; } + public int getPossibleAnswerLength() { + return possibleAnswer.length(); + } + public boolean isValid(@NotNull final Document document) { boolean isLineValid = line < document.getLineCount() && line >= 0; if (!isLineValid) return false; @@ -103,18 +116,6 @@ public class AnswerPlaceholder implements Comparable { return isLengthValid && isStartValid; } - public int compareTo(@NotNull Object o) { - AnswerPlaceholder answerPlaceholder = (AnswerPlaceholder)o; - if (answerPlaceholder.getTaskFile() != myTaskFile) { - throw new ClassCastException(); - } - int lineDiff = line - answerPlaceholder.line; - if (lineDiff == 0) { - return start - answerPlaceholder.start; - } - return lineDiff; - } - /** * Returns window to its initial state */ diff --git a/python/educational/src/com/jetbrains/edu/courseFormat/Lesson.java b/python/educational/src/com/jetbrains/edu/courseFormat/Lesson.java index be451ca17fff..e697476d7846 100644 --- a/python/educational/src/com/jetbrains/edu/courseFormat/Lesson.java +++ b/python/educational/src/com/jetbrains/edu/courseFormat/Lesson.java @@ -2,6 +2,7 @@ package com.jetbrains.edu.courseFormat; import com.google.gson.annotations.SerializedName; import com.intellij.util.xmlb.annotations.Transient; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -53,4 +54,8 @@ public class Lesson { public void setCourse(Course course) { myCourse = course; } + + public void addTask(@NotNull final Task task) { + taskList.add(task); + } } diff --git a/python/educational/src/com/jetbrains/edu/courseFormat/Task.java b/python/educational/src/com/jetbrains/edu/courseFormat/Task.java index 588a1d0808a0..7ba1b3e9d217 100644 --- a/python/educational/src/com/jetbrains/edu/courseFormat/Task.java +++ b/python/educational/src/com/jetbrains/edu/courseFormat/Task.java @@ -23,6 +23,12 @@ public class Task { @Transient private Lesson myLesson; + public Task() {} + + public Task(@NotNull final String name) { + this.name = name; + } + public String getName() { return name; } @@ -59,10 +65,21 @@ public class Task { return taskFiles; } + @Nullable + public TaskFile getTaskFile(final String name) { + return name != null ? taskFiles.get(name) : null; + } + public boolean isTaskFile(@NotNull final String fileName) { return taskFiles.get(fileName) != null; } + public void addTaskFile(@NotNull final String name, int index) { + TaskFile taskFile = new TaskFile(); + taskFile.setIndex(index); + taskFiles.put(name, taskFile); + } + @Nullable public TaskFile getFile(@NotNull final String fileName) { return taskFiles.get(fileName); diff --git a/python/educational/src/com/jetbrains/edu/courseFormat/TaskFile.java b/python/educational/src/com/jetbrains/edu/courseFormat/TaskFile.java index 25230e68b9ae..f98b1bc19bb7 100644 --- a/python/educational/src/com/jetbrains/edu/courseFormat/TaskFile.java +++ b/python/educational/src/com/jetbrains/edu/courseFormat/TaskFile.java @@ -53,6 +53,10 @@ public class TaskFile { this.myAnswerPlaceholders = answerPlaceholders; } + public void addAnswerPlaceholder(AnswerPlaceholder answerPlaceholder) { + myAnswerPlaceholders.add(answerPlaceholder); + } + public int getIndex() { return myIndex; } @@ -112,7 +116,6 @@ public class TaskFile { target.setAnswerPlaceholders(windowsCopy); } - public void setUserCreated(boolean userCreated) { myUserCreated = userCreated; }