efc81bc33be7f2c19289130776e6f2470a9db442
[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         FileEditorManager.getInstance(project).openFile(vf, true);
96         if (!taskFile.getAnswerPlaceholders().isEmpty()) {
97           shouldBeActive = vf;
98         }
99       }
100     }
101     return shouldBeActive != null ? shouldBeActive : getFirstTaskFile(taskDir, project);
102   }
103
104   @Nullable
105   private static VirtualFile getFirstTaskFile(@NotNull final VirtualFile taskDir, @NotNull final Project project) {
106     for (VirtualFile virtualFile : taskDir.getChildren()) {
107       if (StudyUtils.getTaskFile(project, virtualFile) != null) {
108         return virtualFile;
109       }
110     }
111     return null;
112   }
113
114   @Override
115   public void actionPerformed(AnActionEvent e) {
116     Project project = e.getProject();
117     if (project == null) {
118       return;
119     }
120     navigateTask(project);
121   }
122
123   protected abstract Task getTargetTask(@NotNull final Task sourceTask);
124
125   @Override
126   public void update(AnActionEvent e) {
127     StudyUtils.updateAction(e);
128     Project project = e.getProject();
129     if (project == null) {
130       return;
131     }
132     StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
133     StudyState studyState = new StudyState(studyEditor);
134     if (!studyState.isValid()) {
135       return;
136     }
137     if (getTargetTask(studyState.getTask()) == null) {
138       e.getPresentation().setEnabled(false);
139     }
140   }
141 }