add information about active subtask to project view node
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / projectView / StudyDirectoryNode.java
1 package com.jetbrains.edu.learning.projectView;
2
3 import com.intellij.ide.projectView.PresentationData;
4 import com.intellij.ide.projectView.ProjectView;
5 import com.intellij.ide.projectView.ViewSettings;
6 import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
7 import com.intellij.openapi.fileEditor.FileEditorManager;
8 import com.intellij.openapi.project.Project;
9 import com.intellij.openapi.vfs.VirtualFile;
10 import com.intellij.psi.PsiDirectory;
11 import com.intellij.psi.PsiElement;
12 import com.intellij.ui.JBColor;
13 import com.intellij.ui.SimpleTextAttributes;
14 import com.jetbrains.edu.learning.StudyTaskManager;
15 import com.jetbrains.edu.learning.StudyUtils;
16 import com.jetbrains.edu.learning.core.EduNames;
17 import com.jetbrains.edu.learning.core.EduUtils;
18 import com.jetbrains.edu.learning.courseFormat.*;
19 import icons.InteractiveLearningIcons;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
22
23 import javax.swing.*;
24 import java.awt.*;
25 import java.util.Map;
26
27 public class StudyDirectoryNode extends PsiDirectoryNode {
28   public static final JBColor LIGHT_GREEN = new JBColor(new Color(0, 134, 0), new Color(98, 150, 85));
29   protected final PsiDirectory myValue;
30   protected final Project myProject;
31
32   public StudyDirectoryNode(@NotNull final Project project,
33                             PsiDirectory value,
34                             ViewSettings viewSettings) {
35     super(project, value, viewSettings);
36     myValue = value;
37     myProject = project;
38   }
39
40   @Override
41   protected void updateImpl(PresentationData data) {
42     String valueName = myValue.getName();
43     StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(myProject);
44     Course course = studyTaskManager.getCourse();
45     if (course == null) {
46       return;
47     }
48     if (valueName.equals(myProject.getBaseDir().getName())) {
49       data.clearText();
50       data.setIcon(InteractiveLearningIcons.Course);
51       data.addText(course.getName(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, JBColor.BLACK));
52     }
53     else if (valueName.contains(EduNames.TASK)) {
54       VirtualFile taskVirtualFile = myValue.getVirtualFile();
55       VirtualFile lessonVirtualFile = taskVirtualFile.getParent();
56       if (lessonVirtualFile != null) {
57         Lesson lesson = course.getLesson(lessonVirtualFile.getName());
58         if (lesson != null) {
59           Task task = lesson.getTask(taskVirtualFile.getName());
60           if (task != null) {
61             setStudyAttributes(task, data, task.getName());
62           }
63         }
64       }
65     }
66     else if (valueName.contains(EduNames.LESSON)) {
67       int lessonIndex = Integer.parseInt(valueName.substring(EduNames.LESSON.length())) - 1;
68       Lesson lesson = course.getLessons().get(lessonIndex);
69       setStudyAttributes(lesson, data, lesson.getName());
70       data.setPresentableText(valueName);
71     }
72     else if (valueName.contains(EduNames.SANDBOX_DIR)) {
73       if (myValue.getParent() != null) {
74         final String parentName = myValue.getParent().getName();
75         if (!parentName.contains(EduNames.SANDBOX_DIR)) {
76           data.setPresentableText(EduNames.SANDBOX_DIR);
77           data.setIcon(InteractiveLearningIcons.Sandbox);
78         }
79       }
80     }
81     data.setPresentableText(valueName);
82   }
83
84   @Override
85   public int getTypeSortWeight(boolean sortByType) {
86     String name = myValue.getName();
87     if (name.contains(EduNames.LESSON) || name.contains(EduNames.TASK)) {
88       String logicalName = name.contains(EduNames.LESSON) ? EduNames.LESSON : EduNames.TASK;
89       return EduUtils.getIndex(name, logicalName) + 1;
90     }
91     return name.contains(EduNames.SANDBOX_DIR) ? 0 : 3;
92   }
93
94   private static void setStudyAttributes(Lesson lesson, PresentationData data, String additionalName) {
95     switch (lesson.getStatus()) {
96       case Unchecked: {
97         updatePresentation(data, additionalName, JBColor.BLACK, InteractiveLearningIcons.Lesson);
98         break;
99       }
100       case Solved: {
101         updatePresentation(data, additionalName, LIGHT_GREEN, InteractiveLearningIcons.LessonCompl);
102         break;
103       }
104       case Failed: {
105         updatePresentation(data, additionalName, JBColor.RED, InteractiveLearningIcons.Lesson);
106       }
107     }
108   }
109
110   protected void setStudyAttributes(Task task, PresentationData data, String name) {
111     String additionalInfo = task.hasSubtasks() ? getSubtaskInfo(task) : null;
112     StudyStatus taskStatus = task.getStatus();
113     switch (taskStatus) {
114       case Unchecked: {
115         updatePresentation(data, name, JBColor.BLACK, InteractiveLearningIcons.Task, additionalInfo);
116         break;
117       }
118       case Solved: {
119         updatePresentation(data, name, LIGHT_GREEN, InteractiveLearningIcons.TaskCompl, additionalInfo);
120         break;
121       }
122       case Failed: {
123         updatePresentation(data, name, JBColor.RED, InteractiveLearningIcons.TaskProbl, additionalInfo);
124       }
125     }
126   }
127
128   protected static void updatePresentation(PresentationData data, String name, JBColor color, Icon icon) {
129     updatePresentation(data, name, color, icon, null);
130   }
131
132   protected static void updatePresentation(PresentationData data, String name, JBColor color, Icon icon, @Nullable String additionalInfo) {
133     data.clearText();
134     data.addText(name, new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, color));
135     if (additionalInfo != null) {
136       data.addText(" (" + additionalInfo + ")", SimpleTextAttributes.GRAYED_ATTRIBUTES);
137     }
138     data.setIcon(icon);
139   }
140
141   @Override
142   public boolean canNavigate() {
143     return true;
144   }
145
146   @Override
147   public boolean canNavigateToSource() {
148     return true;
149   }
150
151   @Override
152   public void navigate(boolean requestFocus) {
153     final String myValueName = myValue.getName();
154     if (myValueName.contains(EduNames.TASK)) {
155       TaskFile taskFile = null;
156       VirtualFile virtualFile =  null;
157       for (PsiElement child : myValue.getChildren()) {
158         VirtualFile childFile = child.getContainingFile().getVirtualFile();
159         taskFile = StudyUtils.getTaskFile(myProject, childFile);
160         if (taskFile != null) {
161           virtualFile = childFile;
162           break;
163         }
164       }
165       if (taskFile != null) {
166         VirtualFile taskDir = virtualFile.getParent();
167         Task task = taskFile.getTask();
168         for (VirtualFile openFile : FileEditorManager.getInstance(myProject).getOpenFiles()) {
169           FileEditorManager.getInstance(myProject).closeFile(openFile);
170         }
171         VirtualFile child = null;
172         for (Map.Entry<String, TaskFile> entry: task.getTaskFiles().entrySet()) {
173           VirtualFile file = taskDir.findChild(entry.getKey());
174           if (file != null) {
175             FileEditorManager.getInstance(myProject).openFile(file, true);
176           }
177           if (!entry.getValue().getActivePlaceholders().isEmpty()) {
178             child = file;
179           }
180         }
181         if (child != null) {
182           ProjectView.getInstance(myProject).select(child, child, false);
183           FileEditorManager.getInstance(myProject).openFile(child, true);
184         } else {
185           VirtualFile[] children = taskDir.getChildren();
186           if (children.length > 0) {
187             ProjectView.getInstance(myProject).select(children[0], children[0], false);
188           }
189         }
190       }
191     }
192   }
193
194   @Override
195   public boolean expandOnDoubleClick() {
196     final String myValueName = myValue.getName();
197     if (myValueName.contains(EduNames.TASK)) {
198       return false;
199     }
200     return super.expandOnDoubleClick();
201   }
202
203   @Override
204   protected boolean hasProblemFileBeneath() {
205     return false;
206   }
207
208   @Override
209   public String getNavigateActionText(boolean focusEditor) {
210     return null;
211   }
212
213   private static String getSubtaskInfo(Task task) {
214     int index = task.getActiveSubtaskIndex() + 1;
215     return EduNames.SUBTASK + " " + index + "/" + task.getSubtaskNum();
216   }
217 }