c07888519d153d3cd41003c63926379c187bde62
[idea/community.git] / python / edu / learn-python / src / com / jetbrains / python / edu / actions / StudyShowHintAction.java
1 package com.jetbrains.python.edu.actions;
2
3 import com.intellij.codeInsight.documentation.DocumentationComponent;
4 import com.intellij.codeInsight.documentation.DocumentationManager;
5 import com.intellij.openapi.actionSystem.AnActionEvent;
6 import com.intellij.openapi.editor.Editor;
7 import com.intellij.openapi.editor.LogicalPosition;
8 import com.intellij.openapi.project.DumbAwareAction;
9 import com.intellij.openapi.project.Project;
10 import com.intellij.openapi.ui.popup.JBPopup;
11 import com.intellij.openapi.ui.popup.JBPopupFactory;
12 import com.intellij.openapi.util.Disposer;
13 import com.intellij.psi.PsiElement;
14 import com.intellij.psi.PsiFile;
15 import com.intellij.psi.PsiManager;
16 import com.jetbrains.python.edu.StudyState;
17 import com.jetbrains.python.edu.StudyTaskManager;
18 import com.jetbrains.python.edu.StudyUtils;
19 import com.jetbrains.python.edu.course.Course;
20 import com.jetbrains.python.edu.course.TaskWindow;
21 import com.jetbrains.python.edu.editor.StudyEditor;
22 import icons.StudyIcons;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
25
26 import java.io.File;
27
28 public class StudyShowHintAction extends DumbAwareAction {
29   public static final String ACTION_ID = "ShowHintAction";
30   public static final String SHORTCUT = "ctrl pressed 7";
31   public static final String OUTSIDE_TASK_WINDOW_MESSAGE = "Put caret to answer placeholder to get hint";
32   public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder";
33
34   public StudyShowHintAction() {
35     super("Show hint", "Show hint", StudyIcons.ShowHint);
36   }
37
38   public void actionPerformed(@NotNull AnActionEvent e) {
39     final Project project = e.getProject();
40     if (project == null) {
41       return;
42     }
43     showHint(project);
44   }
45
46   public static void showHint(Project project) {
47     Course course = StudyTaskManager.getInstance(project).getCourse();
48     if (course == null) {
49       return;
50     }
51     StudyState studyState = new StudyState(StudyEditor.getSelectedStudyEditor(project));
52     if (!studyState.isValid()) {
53       return;
54     }
55     PsiFile file = PsiManager.getInstance(project).findFile(studyState.getVirtualFile());
56     final Editor editor = studyState.getEditor();
57     LogicalPosition pos = editor.getCaretModel().getLogicalPosition();
58     TaskWindow taskWindow = studyState.getTaskFile().getTaskWindow(editor.getDocument(), pos);
59     if (file == null) {
60       return;
61     }
62     String hintText = OUTSIDE_TASK_WINDOW_MESSAGE;
63     if (taskWindow != null) {
64       hintText = getHintText(taskWindow, course);
65     }
66     int offset = editor.getDocument().getLineStartOffset(pos.line) + pos.column;
67     PsiElement element = file.findElementAt(offset);
68     DocumentationManager documentationManager = DocumentationManager.getInstance(project);
69     DocumentationComponent component = new DocumentationComponent(documentationManager);
70     component.setData(element != null ? element : file, element != null ? hintText : OUTSIDE_TASK_WINDOW_MESSAGE, true, null);
71     showHintPopUp(project, editor, component);
72   }
73
74   @Nullable
75   private static String getHintText(@NotNull final TaskWindow taskWindow, @NotNull final Course course) {
76     String hintFileName = taskWindow.getHint();
77     String hintText = HINT_NOT_AVAILABLE;
78     if (hintFileName != null && !hintFileName.isEmpty()) {
79       File resourceFile = new File(course.getResourcePath());
80       File resourceRoot = resourceFile.getParentFile();
81       if (resourceRoot != null && resourceRoot.exists()) {
82         File hintsDir = new File(resourceRoot, Course.HINTS_DIR);
83         if (hintsDir.exists()) {
84           hintText = StudyUtils.getFileText(hintsDir.getAbsolutePath(), hintFileName, true);
85         }
86       }
87     }
88     return  hintText != null ? hintText : OUTSIDE_TASK_WINDOW_MESSAGE;
89   }
90
91   private static void showHintPopUp(Project project, Editor editor, DocumentationComponent component) {
92     final JBPopup popup =
93       JBPopupFactory.getInstance().createComponentPopupBuilder(component, component)
94         .setDimensionServiceKey(project, DocumentationManager.JAVADOC_LOCATION_AND_SIZE, false)
95         .setResizable(true)
96         .setMovable(true)
97         .setRequestFocus(true)
98         .createPopup();
99     component.setHint(popup);
100     popup.showInBestPositionFor(editor);
101     Disposer.dispose(component);
102   }
103
104   @Override
105   public void update(@NotNull AnActionEvent e) {
106     StudyUtils.updateAction(e);
107   }
108 }