b049e851fef573656692dde3ae8fff0421040fb0
[idea/community.git] / python / educational-core / course-creator / src / com / jetbrains / edu / coursecreator / CCSubtaskEditorNotificationProvider.java
1 package com.jetbrains.edu.coursecreator;
2
3 import com.intellij.openapi.editor.colors.EditorColors;
4 import com.intellij.openapi.editor.colors.EditorColorsManager;
5 import com.intellij.openapi.fileEditor.FileEditor;
6 import com.intellij.openapi.project.DumbAware;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.ui.popup.JBPopupFactory;
9 import com.intellij.openapi.ui.popup.ListSeparator;
10 import com.intellij.openapi.ui.popup.PopupStep;
11 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
12 import com.intellij.openapi.util.Key;
13 import com.intellij.openapi.vfs.VirtualFile;
14 import com.intellij.ui.EditorNotificationPanel;
15 import com.intellij.ui.EditorNotifications;
16 import com.intellij.ui.awt.RelativePoint;
17 import com.jetbrains.edu.coursecreator.actions.CCNewSubtaskAction;
18 import com.jetbrains.edu.learning.StudySubtaskUtils;
19 import com.jetbrains.edu.learning.StudyUtils;
20 import com.jetbrains.edu.learning.core.EduNames;
21 import com.jetbrains.edu.learning.courseFormat.Task;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
24
25 import java.awt.*;
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29
30 public class CCSubtaskEditorNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> implements DumbAware {
31   private static final Key<EditorNotificationPanel> KEY = Key.create("edu.coursecreator.subtask");
32   public static final String SWITCH_SUBTASK = "Switch subtask";
33   public static final Integer ADD_SUBTASK_ID = -1;
34   private final Project myProject;
35
36   public CCSubtaskEditorNotificationProvider(Project project) {
37     myProject = project;
38   }
39
40   @NotNull
41   @Override
42   public Key<EditorNotificationPanel> getKey() {
43     return KEY;
44   }
45
46   @Nullable
47   @Override
48   public EditorNotificationPanel createNotificationPanel(@NotNull VirtualFile file, @NotNull FileEditor fileEditor) {
49     if (!CCUtils.isCourseCreator(myProject)) {
50       return null;
51     }
52     boolean isTestFile = CCUtils.isTestsFile(myProject, file);
53     if (!isTestFile && StudyUtils.getTaskFile(myProject, file) == null) {
54       return null;
55     }
56     Task task = StudyUtils.getTaskForFile(myProject, file);
57     if (task == null || !task.hasSubtasks()) {
58       return null;
59     }
60     EditorNotificationPanel panel = new EditorNotificationPanel() {
61       @Override
62       public Color getBackground() {
63         Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND);
64         return color == null ? super.getBackground() : color;
65       }
66     };
67     String header = isTestFile ? "test" : "task file";
68     int activeSubtaskIndex = task.getActiveSubtaskIndex() + 1;
69     int subtaskSize = task.getLastSubtaskIndex() + 1;
70     panel.setText("This is " + header + " for " + EduNames.SUBTASK + " " + activeSubtaskIndex + "/" + subtaskSize);
71     panel.createActionLabel(SWITCH_SUBTASK, () -> {
72       ArrayList<Integer> values = new ArrayList<>();
73       for (int i = 0; i <= task.getLastSubtaskIndex(); i++) {
74         values.add(i);
75       }
76       values.add(ADD_SUBTASK_ID);
77       JBPopupFactory.getInstance().createListPopup(new SwitchSubtaskPopupStep(SWITCH_SUBTASK, values, task, file)).show(RelativePoint.getSouthEastOf(panel));
78     });
79     return panel;
80   }
81
82   private class SwitchSubtaskPopupStep extends BaseListPopupStep<Integer> {
83     private final Task myTask;
84     private final VirtualFile myFile;
85
86     public SwitchSubtaskPopupStep(@Nullable String title,
87                                   List<Integer> values,
88                                   Task task, VirtualFile file) {
89       super(title, values);
90       myTask = task;
91       myFile = file;
92     }
93
94     @NotNull
95     @Override
96     public String getTextFor(Integer value) {
97       if (value.equals(ADD_SUBTASK_ID)) {
98         return CCNewSubtaskAction.NEW_SUBTASK;
99       }
100       int subtaskNum = value + 1;
101       String text = EduNames.SUBTASK + " " + subtaskNum;
102       if (value == myTask.getActiveSubtaskIndex()) {
103         text +=  " (selected)";
104       }
105       return text;
106     }
107
108     @Override
109     public PopupStep onChosen(Integer selectedValue, boolean finalChoice) {
110       if (finalChoice) {
111         if (selectedValue.equals(ADD_SUBTASK_ID)) {
112           return doFinalStep(() -> CCNewSubtaskAction.addSubtask(myFile, myProject));
113         }
114         StudySubtaskUtils.switchStep(myProject, myTask, selectedValue);
115       } else {
116         if (hasSubstep(selectedValue)) {
117           return new ActionsPopupStep(myTask, selectedValue);
118         }
119       }
120       return super.onChosen(selectedValue, false);
121     }
122
123     @Override
124     public boolean hasSubstep(Integer selectedValue) {
125       return !selectedValue.equals(ADD_SUBTASK_ID);
126     }
127
128     @Override
129     public int getDefaultOptionIndex() {
130       return myTask.getActiveSubtaskIndex();
131     }
132
133     @Nullable
134     @Override
135     public ListSeparator getSeparatorAbove(Integer value) {
136       return value.equals(ADD_SUBTASK_ID) ? new ListSeparator() : null;
137     }
138   }
139
140   private class ActionsPopupStep extends BaseListPopupStep<String> {
141
142     public static final String SELECT = "Select";
143     public static final String DELETE = "Delete";
144     private final Task myTask;
145     private final int mySubtaskIndex;
146
147     public ActionsPopupStep(Task task, int subtaskIndex) {
148       super(null, Arrays.asList(SELECT, DELETE));
149       myTask = task;
150       mySubtaskIndex = subtaskIndex;
151     }
152
153     @Override
154     public PopupStep onChosen(String selectedValue, boolean finalChoice) {
155       if (finalChoice) {
156         if (selectedValue.equals(SELECT)) {
157           StudySubtaskUtils.switchStep(myProject, myTask, mySubtaskIndex);
158         } else {
159           if (mySubtaskIndex != myTask.getLastSubtaskIndex()) {
160             //TODO: implement
161           } else {
162             //TODO: delete last subtask
163           }
164           return FINAL_CHOICE;
165         }
166       }
167       return super.onChosen(selectedValue, finalChoice);
168     }
169   }
170 }