1 package com.jetbrains.edu.learning;
3 import com.intellij.execution.RunContentExecutor;
4 import com.intellij.execution.configurations.GeneralCommandLine;
5 import com.intellij.execution.process.ProcessHandler;
6 import com.intellij.lang.Language;
7 import com.intellij.openapi.actionSystem.AnActionEvent;
8 import com.intellij.openapi.actionSystem.CommonDataKeys;
9 import com.intellij.openapi.actionSystem.DataContext;
10 import com.intellij.openapi.actionSystem.Presentation;
11 import com.intellij.openapi.application.ApplicationManager;
12 import com.intellij.openapi.diagnostic.Logger;
13 import com.intellij.openapi.editor.Document;
14 import com.intellij.openapi.editor.Editor;
15 import com.intellij.openapi.editor.RangeMarker;
16 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
17 import com.intellij.openapi.editor.colors.EditorColors;
18 import com.intellij.openapi.editor.colors.EditorColorsManager;
19 import com.intellij.openapi.editor.impl.DocumentImpl;
20 import com.intellij.openapi.fileEditor.FileDocumentManager;
21 import com.intellij.openapi.fileEditor.FileEditor;
22 import com.intellij.openapi.fileEditor.FileEditorManager;
23 import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
24 import com.intellij.openapi.progress.ProgressManager;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.project.ProjectManager;
27 import com.intellij.openapi.projectRoots.Sdk;
28 import com.intellij.openapi.ui.MessageType;
29 import com.intellij.openapi.ui.popup.Balloon;
30 import com.intellij.openapi.ui.popup.JBPopupFactory;
31 import com.intellij.openapi.util.Disposer;
32 import com.intellij.openapi.util.io.FileUtil;
33 import com.intellij.openapi.util.text.StringUtil;
34 import com.intellij.openapi.vfs.LocalFileSystem;
35 import com.intellij.openapi.vfs.VfsUtil;
36 import com.intellij.openapi.vfs.VirtualFile;
37 import com.intellij.openapi.wm.ToolWindow;
38 import com.intellij.openapi.wm.ToolWindowManager;
39 import com.intellij.psi.PsiDirectory;
40 import com.intellij.psi.PsiElement;
41 import com.intellij.psi.PsiFile;
42 import com.intellij.ui.JBColor;
43 import com.intellij.ui.awt.RelativePoint;
44 import com.intellij.ui.content.Content;
45 import com.intellij.util.ObjectUtils;
46 import com.intellij.util.TimeoutUtil;
47 import com.intellij.util.containers.ContainerUtil;
48 import com.intellij.util.text.MarkdownUtil;
49 import com.intellij.util.ui.UIUtil;
50 import com.jetbrains.edu.learning.checker.StudyExecutor;
51 import com.jetbrains.edu.learning.checker.StudyTestRunner;
52 import com.jetbrains.edu.learning.core.EduAnswerPlaceholderDeleteHandler;
53 import com.jetbrains.edu.learning.core.EduAnswerPlaceholderPainter;
54 import com.jetbrains.edu.learning.core.EduNames;
55 import com.jetbrains.edu.learning.core.EduUtils;
56 import com.jetbrains.edu.learning.courseFormat.*;
57 import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
58 import com.jetbrains.edu.learning.editor.StudyEditor;
59 import com.jetbrains.edu.learning.ui.StudyToolWindow;
60 import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
61 import com.petebevin.markdown.MarkdownProcessor;
62 import org.jetbrains.annotations.NotNull;
63 import org.jetbrains.annotations.Nullable;
69 import java.util.List;
70 import java.util.concurrent.Callable;
71 import java.util.concurrent.ExecutionException;
72 import java.util.concurrent.Future;
74 public class StudyUtils {
75 private StudyUtils() {
78 private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName());
79 private static final String EMPTY_TASK_TEXT = "Please, open any task to see task description";
80 private static final String ourPrefix = "<html><head><script type=\"text/x-mathjax-config\">\n" +
81 " MathJax.Hub.Config({\n" +
83 " inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ],\n" +
84 " displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ],\n" +
85 " processEscapes: true,\n" +
86 " processEnvironments: true\n" +
88 " displayAlign: 'center',\n" +
89 " \"HTML-CSS\": {\n" +
90 " styles: {'#mydiv': {\"font-size\": %s}},\n" +
91 " preferredFont: null,\n" +
92 " linebreaks: { automatic: true }\n" +
95 "</script><script type=\"text/javascript\"\n" +
96 " src=\"http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML-full\">\n" +
97 " </script></head><body><div id=\"mydiv\">";
99 private static final String ourPostfix = "</div></body></html>";
101 public static void closeSilently(@Nullable final Closeable stream) {
102 if (stream != null) {
106 catch (IOException e) {
112 public static boolean isZip(String fileName) {
113 return fileName.contains(".zip");
117 public static <T> T getFirst(@NotNull final Iterable<T> container) {
118 Iterator<T> iterator = container.iterator();
119 if (!iterator.hasNext()) {
122 return iterator.next();
125 public static boolean indexIsValid(int index, @NotNull final Collection collection) {
126 int size = collection.size();
127 return index >= 0 && index < size;
130 @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
132 public static String getFileText(@Nullable final String parentDir, @NotNull final String fileName, boolean wrapHTML,
133 @NotNull final String encoding) {
134 final File inputFile = parentDir != null ? new File(parentDir, fileName) : new File(fileName);
135 if (!inputFile.exists()) return null;
136 final StringBuilder taskText = new StringBuilder();
137 BufferedReader reader = null;
139 reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), encoding));
141 while ((line = reader.readLine()) != null) {
142 taskText.append(line).append("\n");
144 taskText.append("<br>");
147 return wrapHTML ? UIUtil.toHtml(taskText.toString()) : taskText.toString();
149 catch (IOException e) {
150 LOG.info("Failed to get file text from file " + fileName, e);
153 closeSilently(reader);
158 public static void updateAction(@NotNull final AnActionEvent e) {
159 final Presentation presentation = e.getPresentation();
160 presentation.setEnabled(false);
161 final Project project = e.getProject();
162 if (project != null) {
163 final StudyEditor studyEditor = getSelectedStudyEditor(project);
164 if (studyEditor != null) {
165 presentation.setEnabledAndVisible(true);
170 public static void updateToolWindows(@NotNull final Project project) {
171 final StudyToolWindow studyToolWindow = getStudyToolWindow(project);
172 if (studyToolWindow != null) {
173 String taskText = getTaskText(project);
174 if (taskText != null) {
175 studyToolWindow.setTaskText(taskText, null, project);
178 LOG.warn("Task text is null");
180 studyToolWindow.updateCourseProgress(project);
184 public static void initToolWindows(@NotNull final Project project) {
185 final ToolWindowManager windowManager = ToolWindowManager.getInstance(project);
186 windowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager().removeAllContents(false);
187 StudyToolWindowFactory factory = new StudyToolWindowFactory();
188 factory.createToolWindowContent(project, windowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW));
193 public static StudyToolWindow getStudyToolWindow(@NotNull final Project project) {
194 ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
195 if (toolWindow != null) {
196 Content[] contents = toolWindow.getContentManager().getContents();
197 for (Content content: contents) {
198 JComponent component = content.getComponent();
199 if (component != null && component instanceof StudyToolWindow) {
200 return (StudyToolWindow)component;
207 public static void deleteFile(@NotNull final VirtualFile file) {
209 file.delete(StudyUtils.class);
211 catch (IOException e) {
216 public static File copyResourceFile(@NotNull final String sourceName, @NotNull final String copyName, @NotNull final Project project,
217 @NotNull final Task task)
219 final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
220 final Course course = taskManager.getCourse();
221 int taskNum = task.getIndex();
222 int lessonNum = task.getLesson().getIndex();
223 assert course != null;
224 final String pathToResource = FileUtil.join(course.getCourseDirectory(), EduNames.LESSON + lessonNum, EduNames.TASK + taskNum);
225 final File resourceFile = new File(pathToResource, copyName);
226 FileUtil.copy(new File(pathToResource, sourceName), resourceFile);
231 public static Sdk findSdk(@NotNull final Task task, @NotNull final Project project) {
232 final Language language = task.getLesson().getCourse().getLanguageById();
233 return StudyExecutor.INSTANCE.forLanguage(language).findSdk(project);
237 public static StudyTestRunner getTestRunner(@NotNull final Task task, @NotNull final VirtualFile taskDir) {
238 final Language language = task.getLesson().getCourse().getLanguageById();
239 return StudyExecutor.INSTANCE.forLanguage(language).getTestRunner(task, taskDir);
242 public static RunContentExecutor getExecutor(@NotNull final Project project, @NotNull final Task currentTask,
243 @NotNull final ProcessHandler handler) {
244 final Language language = currentTask.getLesson().getCourse().getLanguageById();
245 return StudyExecutor.INSTANCE.forLanguage(language).getExecutor(project, handler);
248 public static void setCommandLineParameters(@NotNull final GeneralCommandLine cmd,
249 @NotNull final Project project,
250 @NotNull final String filePath,
251 @NotNull final String sdkPath,
252 @NotNull final Task currentTask) {
253 final Language language = currentTask.getLesson().getCourse().getLanguageById();
254 StudyExecutor.INSTANCE.forLanguage(language).setCommandLineParameters(cmd, project, filePath, sdkPath, currentTask);
257 public static void showNoSdkNotification(@NotNull final Task currentTask, @NotNull final Project project) {
258 final Language language = currentTask.getLesson().getCourse().getLanguageById();
259 StudyExecutor.INSTANCE.forLanguage(language).showNoSdkNotification(project);
264 * shows pop up in the center of "check task" button in study editor
266 public static void showCheckPopUp(@NotNull final Project project, @NotNull final Balloon balloon) {
267 final StudyEditor studyEditor = getSelectedStudyEditor(project);
268 assert studyEditor != null;
270 balloon.show(computeLocation(studyEditor.getEditor()), Balloon.Position.above);
271 Disposer.register(project, balloon);
274 public static RelativePoint computeLocation(Editor editor){
276 final Rectangle visibleRect = editor.getComponent().getVisibleRect();
277 Point point = new Point(visibleRect.x + visibleRect.width + 10,
279 return new RelativePoint(editor.getComponent(), point);
284 * returns language manager which contains all the information about language specific file names
287 public static StudyLanguageManager getLanguageManager(@NotNull final Course course) {
288 Language language = course.getLanguageById();
289 return language == null ? null : StudyLanguageManager.INSTANCE.forLanguage(language);
292 public static boolean isTestsFile(@NotNull Project project, @NotNull final String name) {
293 Course course = StudyTaskManager.getInstance(project).getCourse();
294 if (course == null) {
297 StudyLanguageManager manager = getLanguageManager(course);
298 if (manager == null) {
301 return manager.getTestFileName().equals(name);
305 public static TaskFile getTaskFile(@NotNull final Project project, @NotNull final VirtualFile file) {
306 final Course course = StudyTaskManager.getInstance(project).getCourse();
307 if (course == null) {
310 VirtualFile taskDir = file.getParent();
311 if (taskDir == null) {
314 //need this because of multi-module generation
315 if (EduNames.SRC.equals(taskDir.getName())) {
316 taskDir = taskDir.getParent();
317 if (taskDir == null) {
321 final String taskDirName = taskDir.getName();
322 if (taskDirName.contains(EduNames.TASK)) {
323 final VirtualFile lessonDir = taskDir.getParent();
324 if (lessonDir != null) {
325 int lessonIndex = EduUtils.getIndex(lessonDir.getName(), EduNames.LESSON);
326 List<Lesson> lessons = course.getLessons();
327 if (!indexIsValid(lessonIndex, lessons)) {
330 final Lesson lesson = lessons.get(lessonIndex);
331 int taskIndex = EduUtils.getIndex(taskDirName, EduNames.TASK);
332 final List<Task> tasks = lesson.getTaskList();
333 if (!indexIsValid(taskIndex, tasks)) {
336 final Task task = tasks.get(taskIndex);
337 return task.getFile(file.getName());
343 public static void drawAllWindows(Editor editor, TaskFile taskFile) {
344 editor.getMarkupModel().removeAllHighlighters();
345 final Project project = editor.getProject();
346 if (project == null) return;
347 final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
348 for (AnswerPlaceholder answerPlaceholder : taskFile.getAnswerPlaceholders()) {
349 final JBColor color = taskManager.getColor(answerPlaceholder);
350 EduAnswerPlaceholderPainter.drawAnswerPlaceholder(editor, answerPlaceholder, color);
352 final Document document = editor.getDocument();
353 EditorActionManager.getInstance()
354 .setReadonlyFragmentModificationHandler(document, new EduAnswerPlaceholderDeleteHandler(editor));
355 EduAnswerPlaceholderPainter.createGuardedBlocks(editor, taskFile);
356 editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
360 public static StudyEditor getSelectedStudyEditor(@NotNull final Project project) {
362 final FileEditor fileEditor = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow().
363 getSelectedEditor().getSelectedEditorWithProvider().getFirst();
364 if (fileEditor instanceof StudyEditor) {
365 return (StudyEditor)fileEditor;
368 catch (Exception e) {
375 public static Editor getSelectedEditor(@NotNull final Project project) {
376 final StudyEditor studyEditor = getSelectedStudyEditor(project);
377 if (studyEditor != null) {
378 return studyEditor.getEditor();
383 public static void deleteGuardedBlocks(@NotNull final Document document) {
384 if (document instanceof DocumentImpl) {
385 final DocumentImpl documentImpl = (DocumentImpl)document;
386 List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
387 for (final RangeMarker block : blocks) {
388 ApplicationManager.getApplication().invokeLater(() -> ApplicationManager.getApplication().runWriteAction(() -> document.removeGuardedBlock(block)));
395 public static VirtualFile getPatternFile(@NotNull TaskFile taskFile, String name) {
396 Task task = taskFile.getTask();
397 String lessonDir = EduNames.LESSON + String.valueOf(task.getLesson().getIndex());
398 String taskDir = EduNames.TASK + String.valueOf(task.getIndex());
399 Course course = task.getLesson().getCourse();
400 File resourceFile = new File(course.getCourseDirectory());
401 if (!resourceFile.exists()) {
404 String patternPath = FileUtil.join(resourceFile.getPath(), lessonDir, taskDir, name);
405 VirtualFile patternFile = VfsUtil.findFileByIoFile(new File(patternPath), true);
406 if (patternFile == null) {
413 public static Document getPatternDocument(@NotNull final TaskFile taskFile, String name) {
414 VirtualFile patternFile = getPatternFile(taskFile, name);
415 if (patternFile == null) {
418 return FileDocumentManager.getInstance().getDocument(patternFile);
421 public static boolean isRenameableOrMoveable(@NotNull final Project project, @NotNull final Course course, @NotNull final PsiElement element) {
422 if (element instanceof PsiFile) {
423 VirtualFile virtualFile = ((PsiFile)element).getVirtualFile();
424 if (project.getBaseDir().equals(virtualFile.getParent())) {
427 TaskFile file = getTaskFile(project, virtualFile);
431 String name = virtualFile.getName();
432 return !isTestsFile(project, name) && !isTaskDescriptionFile(name);
434 if (element instanceof PsiDirectory) {
435 VirtualFile virtualFile = ((PsiDirectory)element).getVirtualFile();
436 VirtualFile parent = virtualFile.getParent();
437 if (parent == null) {
440 if (project.getBaseDir().equals(parent)) {
443 Lesson lesson = course.getLesson(parent.getName());
444 if (lesson != null) {
445 Task task = lesson.getTask(virtualFile.getName());
454 public static boolean canRenameOrMove(DataContext dataContext) {
455 Project project = CommonDataKeys.PROJECT.getData(dataContext);
456 PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
457 if (element == null || project == null) {
460 Course course = StudyTaskManager.getInstance(project).getCourse();
461 if (course == null || !EduNames.STUDY.equals(course.getCourseMode())) {
465 if (!isRenameableOrMoveable(project, course, element)) {
472 public static String getTaskTextFromTask(@Nullable final VirtualFile taskDirectory, @Nullable final Task task) {
477 String text = task.getText();
478 if (text != null && !text.isEmpty()) {
481 if (taskDirectory != null) {
482 final String prefix = String.format(ourPrefix, EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize());
483 final String taskTextFileHtml = getTaskTextFromTaskName(taskDirectory, EduNames.TASK_HTML);
484 if (taskTextFileHtml != null) return prefix + taskTextFileHtml + ourPostfix;
486 final String taskTextFileMd = getTaskTextFromTaskName(taskDirectory, EduNames.TASK_MD);
487 if (taskTextFileMd != null) return prefix + convertToHtml(taskTextFileMd) + ourPostfix;
493 private static String getTaskTextFromTaskName(@NotNull VirtualFile taskDirectory, @NotNull String taskTextFilename) {
494 VirtualFile taskTextFile = taskDirectory.findChild(taskTextFilename);
495 if (taskTextFile == null) {
496 VirtualFile srcDir = taskDirectory.findChild(EduNames.SRC);
497 if (srcDir != null) {
498 taskTextFile = srcDir.findChild(taskTextFilename);
501 if (taskTextFile != null) {
503 return FileUtil.loadTextAndClose(taskTextFile.getInputStream());
505 catch (IOException e) {
513 public static StudyPluginConfigurator getConfigurator(@NotNull final Project project) {
514 StudyPluginConfigurator[] extensions = StudyPluginConfigurator.EP_NAME.getExtensions();
515 for (StudyPluginConfigurator extension: extensions) {
516 if (extension.accept(project)) {
524 public static StudyTwitterPluginConfigurator getTwitterConfigurator(@NotNull final Project project) {
525 StudyTwitterPluginConfigurator[] extensions = StudyTwitterPluginConfigurator.EP_NAME.getExtensions();
526 for (StudyTwitterPluginConfigurator extension: extensions) {
527 if (extension.accept(project)) {
535 public static String getTaskText(@NotNull final Project project) {
536 TaskFile taskFile = getSelectedTaskFile(project);
537 if (taskFile == null) {
538 return EMPTY_TASK_TEXT;
540 final Task task = taskFile.getTask();
542 return getTaskTextFromTask(task.getTaskDir(project), task);
547 public static TaskFile getSelectedTaskFile(@NotNull Project project) {
548 VirtualFile[] files = FileEditorManager.getInstance(project).getSelectedFiles();
549 TaskFile taskFile = null;
550 for (VirtualFile file : files) {
551 taskFile = getTaskFile(project, file);
552 if (taskFile != null) {
560 public static Task getCurrentTask(@NotNull final Project project) {
561 final TaskFile taskFile = getSelectedTaskFile(project);
562 return taskFile != null ? taskFile.getTask() : null;
565 public static boolean isStudyProject(@NotNull Project project) {
566 return StudyTaskManager.getInstance(project).getCourse() != null;
570 public static Project getStudyProject() {
571 Project studyProject = null;
572 Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
573 for (Project project : openProjects) {
574 if (StudyTaskManager.getInstance(project).getCourse() != null) {
575 studyProject = project;
582 public static File getCourseDirectory(@NotNull Project project, Course course) {
583 final File courseDirectory;
584 if (course.isAdaptive()) {
585 courseDirectory = new File(StudyProjectGenerator.OUR_COURSES_DIR,
586 StudyProjectGenerator.ADAPTIVE_COURSE_PREFIX + course.getName()
587 + "_" + StudyTaskManager.getInstance(project).getUser().getEmail());
590 courseDirectory = new File(StudyProjectGenerator.OUR_COURSES_DIR, course.getName());
592 return courseDirectory;
595 public static boolean hasJavaFx() {
597 Class.forName("javafx.application.Platform");
600 catch (ClassNotFoundException e) {
606 public static Task getTask(@NotNull Project project, @NotNull VirtualFile taskVF) {
607 Course course = StudyTaskManager.getInstance(project).getCourse();
608 if (course == null) {
611 VirtualFile lessonVF = taskVF.getParent();
612 if (lessonVF == null) {
615 Lesson lesson = course.getLesson(lessonVF.getName());
616 if (lesson == null) {
619 return lesson.getTask(taskVF.getName());
623 public static VirtualFile getTaskDir(@NotNull VirtualFile taskFile) {
624 VirtualFile parent = taskFile.getParent();
625 if (parent == null) {
628 String name = parent.getName();
629 if (name.contains(EduNames.TASK)) {
632 if (EduNames.SRC.equals(name)) {
633 return parent.getParent();
639 public static Task getTaskForFile(@NotNull Project project, @NotNull VirtualFile taskFile) {
640 VirtualFile taskDir = getTaskDir(taskFile);
641 if (taskDir == null) {
644 return getTask(project, taskDir);
647 // supposed to be called under progress
649 public static <T> T execCancelable(@NotNull final Callable<T> callable) {
650 final Future<T> future = ApplicationManager.getApplication().executeOnPooledThread(callable);
652 while (!future.isCancelled() && !future.isDone()) {
653 ProgressManager.checkCanceled();
654 TimeoutUtil.sleep(500);
658 result = future.get();
660 catch (InterruptedException | ExecutionException e) {
661 LOG.warn(e.getMessage());
667 public static Task getTaskFromSelectedEditor(Project project) {
668 final StudyEditor editor = getSelectedStudyEditor(project);
670 if (editor != null) {
671 final TaskFile file = editor.getTaskFile();
672 task = file.getTask();
677 private static String convertToHtml(@NotNull final String content) {
678 ArrayList<String> lines = ContainerUtil.newArrayList(content.split("\n|\r|\r\n"));
679 MarkdownUtil.replaceHeaders(lines);
680 MarkdownUtil.replaceCodeBlock(lines);
682 return new MarkdownProcessor().markdown(StringUtil.join(lines, "\n"));
685 public static boolean isTaskDescriptionFile(@NotNull final String fileName) {
686 return EduNames.TASK_HTML.equals(fileName) || EduNames.TASK_MD.equals(fileName);
690 public static VirtualFile findTaskDescriptionVirtualFile(@NotNull VirtualFile taskDir) {
691 return ObjectUtils.chooseNotNull(taskDir.findChild(EduNames.TASK_HTML), taskDir.findChild(EduNames.TASK_MD));
695 public static String getTaskDescriptionFileName(final boolean useHtml) {
696 return useHtml ? EduNames.TASK_HTML : EduNames.TASK_MD;
700 public static File createTaskDescriptionFile(@NotNull final File parent) {
701 if(new File(parent, EduNames.TASK_HTML).exists()) {
702 return new File(parent, EduNames.TASK_HTML);
705 return new File(parent, EduNames.TASK_MD);
710 public static Document getDocument(String basePath, int lessonIndex, int taskIndex, String fileName) {
711 String taskPath = FileUtil.join(basePath, EduNames.LESSON + lessonIndex, EduNames.TASK + taskIndex);
712 VirtualFile taskFile = LocalFileSystem.getInstance().findFileByPath(FileUtil.join(taskPath, fileName));
713 if (taskFile == null) {
714 taskFile = LocalFileSystem.getInstance().findFileByPath(FileUtil.join(taskPath, EduNames.SRC, fileName));
716 if (taskFile == null) {
719 return FileDocumentManager.getInstance().getDocument(taskFile);
722 public static void showErrorPopupOnToolbar(@NotNull Project project) {
723 final Balloon balloon =
724 JBPopupFactory.getInstance().createHtmlTextBalloonBuilder("Couldn't post your reaction", MessageType.ERROR, null).createBalloon();
725 showCheckPopUp(project, balloon);