make method static
[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.intellij.util.ui.tree.TreeUtil;
12 import com.jetbrains.edu.learning.StudyState;
13 import com.jetbrains.edu.learning.StudyUtils;
14 import com.jetbrains.edu.learning.core.EduNames;
15 import com.jetbrains.edu.learning.courseFormat.Task;
16 import com.jetbrains.edu.learning.courseFormat.TaskFile;
17 import com.jetbrains.edu.learning.editor.StudyEditor;
18 import org.jetbrains.annotations.NotNull;
19 import org.jetbrains.annotations.Nullable;
20
21 import javax.swing.*;
22 import javax.swing.tree.TreePath;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Map;
26
27
28 abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut {
29   public StudyTaskNavigationAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) {
30     super(text, description, icon);
31   }
32
33   public void navigateTask(@NotNull final Project project) {
34     StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
35     StudyState studyState = new StudyState(studyEditor);
36     if (!studyState.isValid()) {
37       return;
38     }
39     Task nextTask = getTargetTask(studyState.getTask());
40     if (nextTask == null) {
41       return;
42     }
43     for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) {
44       FileEditorManager.getInstance(project).closeFile(file);
45     }
46     int nextTaskIndex = nextTask.getIndex();
47     int lessonIndex = nextTask.getLesson().getIndex();
48     Map<String, TaskFile> nextTaskFiles = nextTask.getTaskFiles();
49     VirtualFile projectDir = project.getBaseDir();
50     String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex);
51     if (projectDir == null) {
52       return;
53     }
54     VirtualFile lessonDir = projectDir.findChild(lessonDirName);
55     if (lessonDir == null) {
56       return;
57     }
58     String taskDirName = EduNames.TASK + String.valueOf(nextTaskIndex);
59     VirtualFile taskDir = lessonDir.findChild(taskDirName);
60     if (taskDir == null) {
61       return;
62     }
63     if (nextTaskFiles.isEmpty()) {
64       ProjectView.getInstance(project).select(taskDir, taskDir, false);
65       return;
66     }
67
68     VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir);
69
70     updateProjectView(project, shouldBeActive);
71
72     ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN);
73     if (runToolWindow != null) {
74       runToolWindow.hide(null);
75     }
76   }
77
78   private static void updateProjectView(@NotNull Project project, VirtualFile shouldBeActive) {
79     JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree();
80     if (shouldBeActive != null) {
81       ProjectView.getInstance(project).selectCB(shouldBeActive, shouldBeActive, false).doWhenDone(() -> {
82         List<TreePath> paths = TreeUtil.collectExpandedPaths(tree);
83         List<TreePath> toCollapse = new ArrayList<TreePath>();
84         TreePath selectedPath = tree.getSelectionPath();
85         for (TreePath treePath : paths) {
86           if (treePath.isDescendant(selectedPath)) {
87             continue;
88           }
89           if (toCollapse.isEmpty()) {
90             toCollapse.add(treePath);
91             continue;
92           }
93           for (int i = 0; i < toCollapse.size(); i++) {
94             TreePath path = toCollapse.get(i);
95             if (treePath.isDescendant(path)) {
96               toCollapse.set(i, treePath);
97             }  else {
98               if (!path.isDescendant(treePath)) {
99                 toCollapse.add(treePath);
100               }
101             }
102           }
103         }
104         for (TreePath path : toCollapse) {
105           tree.collapsePath(path);
106           tree.fireTreeCollapsed(path);
107         }
108       });
109       FileEditorManager.getInstance(project).openFile(shouldBeActive, true);
110     }
111   }
112
113   @Nullable
114   protected VirtualFile getFileToActivate(@NotNull Project project, Map<String, TaskFile> nextTaskFiles, VirtualFile taskDir) {
115     VirtualFile shouldBeActive = null;
116     for (Map.Entry<String, TaskFile> entry : nextTaskFiles.entrySet()) {
117       String name = entry.getKey();
118       TaskFile taskFile = entry.getValue();
119       VirtualFile srcDir = taskDir.findChild(EduNames.SRC);
120       VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name);
121       if (vf != null) {
122         if (shouldBeActive != null) {
123           FileEditorManager.getInstance(project).openFile(vf, true);
124         }
125         if (shouldBeActive == null && !taskFile.getAnswerPlaceholders().isEmpty()) {
126           shouldBeActive = vf;
127         }
128       }
129     }
130     return shouldBeActive != null ? shouldBeActive : getFirstTaskFile(taskDir, project);
131   }
132
133   @Nullable
134   private static VirtualFile getFirstTaskFile(@NotNull final VirtualFile taskDir, @NotNull final Project project) {
135     for (VirtualFile virtualFile : taskDir.getChildren()) {
136       if (StudyUtils.getTaskFile(project, virtualFile) != null) {
137         return virtualFile;
138       }
139     }
140     return null;
141   }
142
143   @Override
144   public void actionPerformed(AnActionEvent e) {
145     Project project = e.getProject();
146     if (project == null) {
147       return;
148     }
149     navigateTask(project);
150   }
151
152   protected abstract Task getTargetTask(@NotNull final Task sourceTask);
153
154   @Override
155   public void update(AnActionEvent e) {
156     StudyUtils.updateAction(e);
157     Project project = e.getProject();
158     if (project == null) {
159       return;
160     }
161     StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project);
162     StudyState studyState = new StudyState(studyEditor);
163     if (!studyState.isValid()) {
164       return;
165     }
166     if (getTargetTask(studyState.getTask()) == null) {
167       e.getPresentation().setEnabled(false);
168     }
169   }
170 }