791d7fb0efae49949a7713ab5c2248292ba7f748
[idea/community.git] / python / educational-core / course-creator / src / com / jetbrains / edu / coursecreator / actions / CCAddAnswerPlaceholder.java
1 package com.jetbrains.edu.coursecreator.actions;
2
3 import com.intellij.openapi.actionSystem.AnActionEvent;
4 import com.intellij.openapi.actionSystem.CommonDataKeys;
5 import com.intellij.openapi.actionSystem.Presentation;
6 import com.intellij.openapi.diagnostic.Logger;
7 import com.intellij.openapi.editor.Document;
8 import com.intellij.openapi.editor.Editor;
9 import com.intellij.openapi.editor.SelectionModel;
10 import com.intellij.openapi.project.DumbAwareAction;
11 import com.intellij.openapi.project.Project;
12 import com.intellij.openapi.ui.DialogWrapper;
13 import com.intellij.psi.PsiDirectory;
14 import com.intellij.psi.PsiDocumentManager;
15 import com.intellij.psi.PsiFile;
16 import com.intellij.ui.JBColor;
17 import com.jetbrains.edu.learning.core.EduAnswerPlaceholderPainter;
18 import com.jetbrains.edu.coursecreator.CCProjectService;
19 import com.jetbrains.edu.coursecreator.ui.CCCreateAnswerPlaceholderDialog;
20 import com.jetbrains.edu.learning.courseFormat.*;
21 import org.jetbrains.annotations.NotNull;
22
23 import java.util.List;
24
25 public class CCAddAnswerPlaceholder extends DumbAwareAction {
26   private static final Logger LOG = Logger.getInstance(CCAddAnswerPlaceholder.class);
27
28   public CCAddAnswerPlaceholder() {
29     super("Add Answer Placeholder", "Add answer placeholder", null);
30   }
31
32
33   private static boolean arePlaceholdersIntersect(@NotNull final TaskFile taskFile, @NotNull final Document document, int start, int end) {
34     List<AnswerPlaceholder> answerPlaceholders = taskFile.getAnswerPlaceholders();
35     for (AnswerPlaceholder existingAnswerPlaceholder : answerPlaceholders) {
36       int twStart = existingAnswerPlaceholder.getRealStartOffset(document);
37       int twEnd = existingAnswerPlaceholder.getPossibleAnswerLength() + twStart;
38       if ((start >= twStart && start < twEnd) || (end > twStart && end <= twEnd) ||
39           (twStart >= start && twStart < end) || (twEnd > start && twEnd <= end)) {
40         return true;
41       }
42     }
43     return false;
44   }
45
46   @Override
47   public void actionPerformed(@NotNull AnActionEvent e) {
48     final Project project = e.getData(CommonDataKeys.PROJECT);
49     if (project == null) {
50       return;
51     }
52     final PsiFile file = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
53     if (file == null) return;
54     final Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
55     if (editor == null) return;
56     final SelectionModel model = editor.getSelectionModel();
57     final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
58     if (document == null) return;
59     final int start = model.getSelectionStart();
60     final int end = model.getSelectionEnd();
61     final int lineNumber = document.getLineNumber(start);
62     int realStart = start - document.getLineStartOffset(lineNumber);
63
64     final CCProjectService service = CCProjectService.getInstance(project);
65     final PsiDirectory taskDir = file.getContainingDirectory();
66     final PsiDirectory lessonDir = taskDir.getParent();
67     if (lessonDir == null) return;
68
69     final TaskFile taskFile = service.getTaskFile(file.getVirtualFile());
70     if (taskFile == null) {
71       return;
72     }
73     if (arePlaceholdersIntersect(taskFile, document, start, end)) {
74       return;
75     }
76     final AnswerPlaceholder answerPlaceholder = new AnswerPlaceholder();
77     answerPlaceholder.setLine(lineNumber);
78     answerPlaceholder.setStart(realStart);
79     answerPlaceholder.setPossibleAnswer(model.getSelectedText());
80
81     CCCreateAnswerPlaceholderDialog dlg = new CCCreateAnswerPlaceholderDialog(project, answerPlaceholder
82     );
83     dlg.show();
84     if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
85       return;
86     }
87     int index = taskFile.getAnswerPlaceholders().size() + 1;
88     answerPlaceholder.setIndex(index);
89     taskFile.addAnswerPlaceholder(answerPlaceholder);
90     taskFile.sortAnswerPlaceholders();
91     EduAnswerPlaceholderPainter.drawAnswerPlaceholder(editor, answerPlaceholder, false, JBColor.BLUE);
92     EduAnswerPlaceholderPainter.createGuardedBlocks(editor, answerPlaceholder, false);
93   }
94
95   @Override
96   public void update(@NotNull AnActionEvent event) {
97     if (!CCProjectService.setCCActionAvailable(event)) {
98       return;
99     }
100     final Presentation presentation = event.getPresentation();
101     final Project project = event.getData(CommonDataKeys.PROJECT);
102     if (project == null) {
103       presentation.setVisible(false);
104       presentation.setEnabled(false);
105       return;
106     }
107     final Editor editor = CommonDataKeys.EDITOR.getData(event.getDataContext());
108     final PsiFile file = CommonDataKeys.PSI_FILE.getData(event.getDataContext());
109     if (editor == null || file == null) {
110       presentation.setVisible(false);
111       presentation.setEnabled(false);
112       return;
113     }
114     SelectionModel selectionModel = editor.getSelectionModel();
115     if (!selectionModel.hasSelection()) {
116       presentation.setVisible(false);
117       presentation.setEnabled(false);
118       return;
119     }
120     int start = selectionModel.getSelectionStart();
121     int end = selectionModel.getSelectionEnd();
122
123     final CCProjectService service = CCProjectService.getInstance(project);
124     final PsiDirectory taskDir = file.getContainingDirectory();
125     final PsiDirectory lessonDir = taskDir.getParent();
126     if (lessonDir == null) return;
127
128     final Course course = service.getCourse();
129     final Lesson lesson = course.getLesson(lessonDir.getName());
130     if (lesson == null) {
131       presentation.setVisible(false);
132       presentation.setEnabled(false);
133       return;
134     }
135     final Task task = lesson.getTask(taskDir.getName());
136     if (task == null) {
137       presentation.setVisible(false);
138       presentation.setEnabled(false);
139       return;
140     }
141     TaskFile taskFile = service.getTaskFile(file.getVirtualFile());
142     if (taskFile == null) {
143       LOG.info("could not find task file");
144       presentation.setVisible(false);
145       presentation.setEnabled(false);
146       return;
147     }
148     if (arePlaceholdersIntersect(taskFile, editor.getDocument(), start, end)) {
149       presentation.setVisible(false);
150       presentation.setEnabled(false);
151       return;
152     }
153     presentation.setVisible(true);
154     presentation.setEnabled(true);
155   }
156 }