EDU-536 Open task file with placeholders when new task opened
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / actions / StudyTaskNavigationAction.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.fileEditor.FileEditorManager;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.vfs.VirtualFile;
8 import com.intellij.openapi.wm.ToolWindow;
9 import com.intellij.openapi.wm.ToolWindowId;
10 import com.intellij.openapi.wm.ToolWindowManager;
11 import com.jetbrains.edu.learning.StudyState;
12 import com.jetbrains.edu.learning.StudyUtils;
13 import com.jetbrains.edu.learning.core.EduNames;
14 import com.jetbrains.edu.learning.courseFormat.Task;
15 import com.jetbrains.edu.learning.courseFormat.TaskFile;
16 import com.jetbrains.edu.learning.editor.StudyEditor;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
19
20 import javax.swing.*;
21 import javax.swing.tree.TreePath;
22 import java.util.Map;
23
24
25 abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut {
26   public StudyTaskNavigationAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) {
27     super(text, description, icon);
28   }
29
30   public void navigateTask(@NotNull final Project project) {
31     StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
32     StudyState studyState = new StudyState(studyEditor);
33     if (!studyState.isValid()) {
34       return;
35     }
36     Task nextTask = getTargetTask(studyState.getTask());
37     if (nextTask == null) {
38       return;
39     }
40     for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) {
41       FileEditorManager.getInstance(project).closeFile(file);
42     }
43     int nextTaskIndex = nextTask.getIndex();
44     int lessonIndex = nextTask.getLesson().getIndex();
45     Map<String, TaskFile> nextTaskFiles = nextTask.getTaskFiles();
46     VirtualFile projectDir = project.getBaseDir();
47     String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex);
48     if (projectDir == null) {
49       return;
50     }
51     VirtualFile lessonDir = projectDir.findChild(lessonDirName);
52     if (lessonDir == null) {
53       return;
54     }
55     String taskDirName = EduNames.TASK + String.valueOf(nextTaskIndex);
56     VirtualFile taskDir = lessonDir.findChild(taskDirName);
57     if (taskDir == null) {
58       return;
59     }
60     if (nextTaskFiles.isEmpty()) {
61       ProjectView.getInstance(project).select(taskDir, taskDir, false);
62       return;
63     }
64
65     VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir);
66     JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree();
67     TreePath path = tree.getSelectionPath();
68     if (path != null) {
69       TreePath oldSelectionPath = path.getParentPath();
70       if (oldSelectionPath != null) {
71         tree.collapsePath(oldSelectionPath);
72         tree.fireTreeCollapsed(oldSelectionPath);
73       }
74     }
75     if (shouldBeActive != null) {
76       ProjectView.getInstance(project).select(shouldBeActive, shouldBeActive, false);
77       FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
78     }
79
80     ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN);
81     if (runToolWindow != null) {
82       runToolWindow.hide(null);
83     }
84   }
85
86   @Nullable
87   protected VirtualFile getFileToActivate(@NotNull Project project, Map<String, TaskFile> nextTaskFiles, VirtualFile taskDir) {
88     VirtualFile shouldBeActive = null;
89     for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
90       String name = entry.getKey();
91       TaskFile taskFile = entry.getValue();
92       VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
93       VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name);
94       if (vf != null) {
95         if (shouldBeActive != null) {
96           FileEditorManager.getInstance(project).openFile(vf, true);
97         }
98         if (shouldBeActive == null && !taskFile.getAnswerPlaceholders().isEmpty()) {
99           shouldBeActive = vf;
100         }
101       }
102     }
103     return shouldBeActive != null ? shouldBeActive : getFirstTaskFile(taskDir, project);
104   }
105
106   @Nullable
107   private static VirtualFile getFirstTaskFile(@NotNull final VirtualFile taskDir, @NotNull final Project project) {
108     for (VirtualFile virtualFile : taskDir.getChildren()) {
109       if (StudyUtils.getTaskFile(project, virtualFile) != null) {
110         return virtualFile;
111       }
112     }
113     return null;
114   }
115
116   @Override
117   public void actionPerformed(AnActionEvent e) {
118     Project project = e.getProject();
119     if (project == null) {
120       return;
121     }
122     navigateTask(project);
123   }
124
125   protected abstract Task getTargetTask(@NotNull final Task sourceTask);
126
127   @Override
128   public void update(AnActionEvent e) {
129     StudyUtils.updateAction(e);
130     Project project = e.getProject();
131     if (project == null) {
132       return;
133     }
134     StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
135     StudyState studyState = new StudyState(studyEditor);
136     if (!studyState.isValid()) {
137       return;
138     }
139     if (getTargetTask(studyState.getTask()) == null) {
140       e.getPresentation().setEnabled(false);
141     }
142   }
143 }