fixed bugs after huge refactoring
[idea/community.git] / python / educational / interactive-learning / src / com / jetbrains / edu / learning / actions / StudyRefreshTaskFileAction.java
1 package com.jetbrains.edu.learning.actions;
2
3 import com.intellij.ide.projectView.ProjectView;
4 import com.intellij.openapi.actionSystem.AnActionEvent;
5 import com.intellij.openapi.application.ApplicationManager;
6 import com.intellij.openapi.command.CommandProcessor;
7 import com.intellij.openapi.diagnostic.Logger;
8 import com.intellij.openapi.editor.Document;
9 import com.intellij.openapi.editor.Editor;
10 import com.intellij.openapi.fileEditor.FileDocumentManager;
11 import com.intellij.openapi.project.DumbAwareAction;
12 import com.intellij.openapi.project.Project;
13 import com.intellij.openapi.ui.MessageType;
14 import com.intellij.openapi.ui.popup.Balloon;
15 import com.intellij.openapi.ui.popup.BalloonBuilder;
16 import com.intellij.openapi.ui.popup.JBPopupFactory;
17 import com.intellij.openapi.util.Disposer;
18 import com.intellij.openapi.util.io.FileUtil;
19 import com.intellij.openapi.vfs.VfsUtil;
20 import com.intellij.openapi.vfs.VirtualFile;
21 import com.intellij.openapi.wm.IdeFocusManager;
22 import com.intellij.problems.WolfTheProblemSolver;
23 import com.jetbrains.edu.EduAnswerPlaceholderPainter;
24 import com.jetbrains.edu.EduNames;
25 import com.jetbrains.edu.EduUtils;
26 import com.jetbrains.edu.courseFormat.AnswerPlaceholder;
27 import com.jetbrains.edu.courseFormat.Course;
28 import com.jetbrains.edu.courseFormat.Task;
29 import com.jetbrains.edu.courseFormat.TaskFile;
30 import com.jetbrains.edu.learning.StudyState;
31 import com.jetbrains.edu.learning.StudyTaskManager;
32 import com.jetbrains.edu.learning.StudyUtils;
33 import com.jetbrains.edu.learning.courseFormat.StudyStatus;
34 import com.jetbrains.edu.learning.editor.StudyEditor;
35 import com.jetbrains.edu.learning.navigation.StudyNavigator;
36 import org.jetbrains.annotations.NotNull;
37
38 import java.io.File;
39
40 public class StudyRefreshTaskFileAction extends DumbAwareAction {
41   public static final String ACTION_ID = "RefreshTaskAction";
42   public static final String SHORTCUT = "ctrl shift pressed X";
43   private static final Logger LOG = Logger.getInstance(StudyRefreshTaskFileAction.class.getName());
44
45   public static void refresh(@NotNull final Project project) {
46     ApplicationManager.getApplication().invokeLater(new Runnable() {
47       @Override
48       public void run() {
49         ApplicationManager.getApplication().runWriteAction(new Runnable() {
50           @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
51           @Override
52           public void run() {
53             StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
54             StudyState studyState = new StudyState(studyEditor);
55             if (studyEditor == null || !studyState.isValid()) {
56               LOG.info("RefreshTaskFileAction was invoked outside of Study Editor");
57               return;
58             }
59             refreshFile(studyState, project);
60           }
61         });
62       }
63     });
64   }
65
66   private static void refreshFile(@NotNull final StudyState studyState, @NotNull final Project project) {
67     final Editor editor = studyState.getEditor();
68     final TaskFile taskFile = studyState.getTaskFile();
69     if (!resetTaskFile(editor.getDocument(), project, taskFile, studyState.getVirtualFile().getName())) {
70       return;
71     }
72     WolfTheProblemSolver.getInstance(project).clearProblems(studyState.getVirtualFile());
73     taskFile.setHighlightErrors(false);
74     StudyUtils.drawAllWindows(editor, taskFile);
75     EduAnswerPlaceholderPainter.createGuardedBlocks(editor, taskFile, true);
76     ApplicationManager.getApplication().invokeLater(new Runnable() {
77       @Override
78       public void run() {
79         IdeFocusManager.getInstance(project).requestFocus(editor.getContentComponent(), true);
80       }
81     });
82
83     StudyNavigator.navigateToFirstAnswerPlaceholder(editor, taskFile);
84     showBalloon(project, "You can start again now", MessageType.INFO);
85   }
86
87   private static boolean resetTaskFile(@NotNull final Document document,
88                                        @NotNull final Project project,
89                                        TaskFile taskFile,
90                                        String name) {
91     if (!resetDocument(project, document, taskFile, name)) {
92       return false;
93     }
94     resetAnswerPlaceholders(taskFile, project);
95     ProjectView.getInstance(project).refresh();
96     StudyUtils.updateStudyToolWindow(project);
97     return true;
98   }
99
100   private static void showBalloon(@NotNull final Project project, String text, @NotNull final MessageType messageType) {
101     BalloonBuilder balloonBuilder =
102       JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, messageType, null);
103     final Balloon balloon = balloonBuilder.createBalloon();
104     StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
105     assert selectedStudyEditor != null;
106     balloon.showInCenterOf(selectedStudyEditor.getRefreshButton());
107     Disposer.register(project, balloon);
108   }
109
110   private static void resetAnswerPlaceholders(TaskFile selectedTaskFile, Project project) {
111     final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
112     for (AnswerPlaceholder answerPlaceholder : selectedTaskFile.getAnswerPlaceholders()) {
113       answerPlaceholder.reset();
114       taskManager.setStatus(answerPlaceholder, StudyStatus.Unchecked);
115     }
116   }
117
118
119   private static boolean resetDocument(@NotNull final Project project,
120                                        @NotNull final Document document,
121                                        @NotNull final TaskFile taskFile,
122                                        String fileName) {
123     StudyEditor.deleteGuardedBlocks(document);
124     taskFile.setTrackChanges(false);
125     clearDocument(document);
126     Task task = taskFile.getTask();
127     String lessonDir = EduNames.LESSON + String.valueOf(task.getLesson().getIndex());
128     String taskDir = EduNames.TASK + String.valueOf(task.getIndex());
129     Course course = task.getLesson().getCourse();
130     File resourceFile = new File(course.getCourseDirectory());
131     if (!resourceFile.exists()) {
132       showBalloon(project, "Course was deleted", MessageType.ERROR);
133       return false;
134     }
135     String patternPath = FileUtil.join(resourceFile.getPath(), lessonDir, taskDir, fileName);
136     VirtualFile patternFile = VfsUtil.findFileByIoFile(new File(patternPath), true);
137     if (patternFile == null) {
138       return false;
139     }
140     final Document patternDocument = FileDocumentManager.getInstance().getDocument(patternFile);
141     if (patternDocument == null) {
142       return false;
143     }
144     document.setText(patternDocument.getCharsSequence());
145     taskFile.setTrackChanges(true);
146     return true;
147   }
148
149   private static void clearDocument(@NotNull final Document document) {
150     final int lineCount = document.getLineCount();
151     if (lineCount != 0) {
152       CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
153         @Override
154         public void run() {
155           document.deleteString(0, document.getLineEndOffset(lineCount - 1));
156         }
157       });
158     }
159   }
160
161   public void actionPerformed(@NotNull AnActionEvent event) {
162     final Project project = event.getProject();
163     if (project != null) {
164       refresh(project);
165     }
166   }
167
168   @Override
169   public void update(AnActionEvent event) {
170     final Project project = event.getProject();
171     if (project != null) {
172       StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project);
173       StudyState studyState = new StudyState(studyEditor);
174       if (studyState.isValid()) {
175         EduUtils.enableAction(event, true);
176       }
177     }
178     EduUtils.enableAction(event, false);
179   }
180 }