From db256da86288ad4b913c7d8665917967dd2910bb Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 15 Jul 2015 21:40:46 +0300 Subject: [PATCH] refactored study editor view - moved task text to the separate toolwindow - moved action buttons to the toolwindow - moved util methods to the StudyUtils --- .../resources/META-INF/plugin.xml | 6 +- .../edu/learning/StudyProjectComponent.java | 20 +- .../jetbrains/edu/learning/StudyUtils.java | 65 ++- .../learning/actions/StudyCheckAction.java | 23 +- .../actions/StudyEditInputAction.java | 24 +- .../actions/StudyNextStudyTaskAction.java | 9 +- .../actions/StudyPreviousStudyTaskAction.java | 11 +- .../actions/StudyRefreshTaskFileAction.java | 20 +- .../edu/learning/actions/StudyRunAction.java | 28 +- .../learning/actions/StudyShowHintAction.java | 9 +- .../actions/StudyTaskNavigationAction.java | 12 +- .../actions/StudyWindowNavigationAction.java | 3 +- .../edu/learning/editor/StudyEditor.java | 415 +----------------- .../editor/StudyEditorFactoryListener.java | 10 + .../edu/learning/ui/StudyCondition.java | 11 - .../edu/learning/ui/StudyToolWindow.java | 81 ++++ .../learning/ui/StudyToolWindowFactory.java | 79 +--- 17 files changed, 277 insertions(+), 549 deletions(-) create mode 100644 python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java diff --git a/python/educational/interactive-learning/resources/META-INF/plugin.xml b/python/educational/interactive-learning/resources/META-INF/plugin.xml index 0c112e2e4bea..57adbc2196e7 100644 --- a/python/educational/interactive-learning/resources/META-INF/plugin.xml +++ b/python/educational/interactive-learning/resources/META-INF/plugin.xml @@ -50,9 +50,9 @@ description="Navigate to the next answer holder"> + description="Navigate to the previous task"/> + description="Navigate to the next task"/> - + blocks = documentImpl.getGuardedBlocks(); + for (final RangeMarker block : blocks) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + document.removeGuardedBlock(block); + } + }); + } + }); + } + } + } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java index 3b8e5f84e5ae..f92c883c9c92 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java @@ -6,6 +6,7 @@ import com.intellij.execution.process.ProcessOutput; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; @@ -14,6 +15,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.TaskInfo; @@ -43,9 +45,11 @@ import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.navigation.StudyNavigator; import com.jetbrains.edu.learning.run.StudySmartChecker; import com.jetbrains.edu.learning.run.StudyTestRunner; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.awt.*; import java.io.IOException; import java.util.List; @@ -58,6 +62,11 @@ public class StudyCheckAction extends DumbAwareAction { public static final String ACTION_ID = "CheckAction"; public static final String SHORTCUT = "ctrl alt pressed ENTER"; + boolean checkInProgress = false; + + public StudyCheckAction() { + super("Check Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Check current task", InteractiveLearningIcons.Resolve); + } private static void flushWindows(@NotNull final Task task, @NotNull final VirtualFile taskDir) { for (Map.Entry entry : task.getTaskFiles().entrySet()) { @@ -115,7 +124,7 @@ public class StudyCheckAction extends DumbAwareAction { CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() { @Override public void run() { - final StudyEditor selectedEditor = StudyEditor.getSelectedStudyEditor(project); + final StudyEditor selectedEditor = StudyUtils.getSelectedStudyEditor(project); if (selectedEditor == null) return; final StudyState studyState = new StudyState(selectedEditor); if (!studyState.isValid()) { @@ -158,7 +167,7 @@ public class StudyCheckAction extends DumbAwareAction { if (testProcess == null) { return; } - selectedEditor.getCheckButton().setEnabled(false); + checkInProgress = true; ProgressManager.getInstance().run(getCheckTask(studyState, testRunner, testProcess, project, selectedEditor)); } }); @@ -202,14 +211,14 @@ public class StudyCheckAction extends DumbAwareAction { drawAllPlaceholders(project, task, taskDir); ProjectView.getInstance(project).refresh(); deleteWindowDescriptions(task, taskDir); - selectedEditor.getCheckButton().setEnabled(true); + checkInProgress = false; } @Override public void onCancel() { taskManager.setStatus(task, statusBeforeCheck); deleteWindowDescriptions(task, taskDir); - selectedEditor.getCheckButton().setEnabled(true); + checkInProgress = false; } @Override @@ -382,7 +391,6 @@ public class StudyCheckAction extends DumbAwareAction { StudyUtils.showCheckPopUp(project, balloon); } - @Override public void actionPerformed(@NotNull AnActionEvent e) { Project project = e.getProject(); @@ -390,4 +398,9 @@ public class StudyCheckAction extends DumbAwareAction { check(project); } } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(!checkInProgress); + } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java index 24d6e31f3fb6..8b11fb42ffd5 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyEditInputAction.java @@ -29,6 +29,7 @@ import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.courseFormat.UserTest; import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.ui.StudyTestContentPanel; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -46,8 +47,12 @@ public class StudyEditInputAction extends DumbAwareAction { private JBEditorTabs tabbedPane; private Map myEditableTabs = new HashMap(); + public StudyEditInputAction() { + super("Watch Test Input", "Watch test input", InteractiveLearningIcons.WatchInput); + } + public void showInput(final Project project) { - final Editor selectedEditor = StudyEditor.getSelectedEditor(project); + final Editor selectedEditor = StudyUtils.getSelectedEditor(project); if (selectedEditor != null) { FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument()); @@ -100,7 +105,7 @@ public class StudyEditInputAction extends DumbAwareAction { .setMovable(true) .setRequestFocus(true) .createPopup(); - StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project); + StudyEditor selectedStudyEditor = StudyUtils.getSelectedStudyEditor(project); assert selectedStudyEditor != null; hint.showInCenterOf(selectedStudyEditor.getComponent()); hint.addListener(new HintClosedListener(currentTask, studyTaskManager)); @@ -219,4 +224,19 @@ public class StudyEditInputAction extends DumbAwareAction { } } } + @Override + public void update(final AnActionEvent e) { + EduUtils.enableAction(e, false); + + final Project project = e.getProject(); + if (project != null) { + StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); + if (studyEditor != null) { + final List userTests = StudyTaskManager.getInstance(project).getUserTests(studyEditor.getTaskFile().getTask()); + if (!userTests.isEmpty()) { + EduUtils.enableAction(e, true); + } + } + } + } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java index 458039259122..d76308bac774 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyNextStudyTaskAction.java @@ -1,7 +1,9 @@ package com.jetbrains.edu.learning.actions; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.KeyboardShortcut; +import com.intellij.openapi.keymap.KeymapUtil; import com.jetbrains.edu.courseFormat.Task; -import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.navigation.StudyNavigator; import org.jetbrains.annotations.NotNull; @@ -12,9 +14,8 @@ public class StudyNextStudyTaskAction extends StudyTaskNavigationAction { public static final String ACTION_ID = "NextTaskAction"; public static final String SHORTCUT = "ctrl pressed PERIOD"; - @Override - protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) { - return selectedStudyEditor.getNextTaskButton(); + public StudyNextStudyTaskAction() { + super("Next Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Navigate to the next task", AllIcons.Actions.Forward); } @Override diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java index 35e8048f49ca..0c3d5b4088ce 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyPreviousStudyTaskAction.java @@ -1,21 +1,22 @@ package com.jetbrains.edu.learning.actions; +import com.intellij.openapi.actionSystem.KeyboardShortcut; +import com.intellij.openapi.keymap.KeymapUtil; import com.jetbrains.edu.courseFormat.Task; -import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.navigation.StudyNavigator; +import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; import javax.swing.*; public class StudyPreviousStudyTaskAction extends StudyTaskNavigationAction { + public StudyPreviousStudyTaskAction() { + super("Previous Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Navigate to the previous task", InteractiveLearningIcons.Prev); + } public static final String ACTION_ID = "PreviousTaskAction"; public static final String SHORTCUT = "ctrl pressed COMMA"; - @Override - protected JButton getButton(@NotNull final StudyEditor selectedStudyEditor) { - return selectedStudyEditor.getPrevTaskButton(); - } @Override protected String getNavigationFinishedMessage() { diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java index 9725e19043b4..151aec37dd85 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRefreshTaskFileAction.java @@ -1,13 +1,16 @@ package com.jetbrains.edu.learning.actions; +import com.intellij.icons.AllIcons; import com.intellij.ide.projectView.ProjectView; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; @@ -35,6 +38,7 @@ import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.navigation.StudyNavigator; import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.io.File; public class StudyRefreshTaskFileAction extends DumbAwareAction { @@ -42,6 +46,10 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction { public static final String SHORTCUT = "ctrl shift pressed X"; private static final Logger LOG = Logger.getInstance(StudyRefreshTaskFileAction.class.getName()); + public StudyRefreshTaskFileAction() { + super("Reset Task File (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Refresh current task", AllIcons.Actions.Refresh); + } + public static void refresh(@NotNull final Project project) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override @@ -50,7 +58,7 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction { @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") @Override public void run() { - StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project); + StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); StudyState studyState = new StudyState(studyEditor); if (studyEditor == null || !studyState.isValid()) { LOG.info("RefreshTaskFileAction was invoked outside of Study Editor"); @@ -101,9 +109,9 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction { BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text, messageType, null); final Balloon balloon = balloonBuilder.createBalloon(); - StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project); + StudyEditor selectedStudyEditor = StudyUtils.getSelectedStudyEditor(project); assert selectedStudyEditor != null; - balloon.showInCenterOf(selectedStudyEditor.getRefreshButton()); + balloon.show(StudyUtils.computeLocation(selectedStudyEditor.getEditor()), Balloon.Position.above); Disposer.register(project, balloon); } @@ -120,7 +128,7 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction { @NotNull final Document document, @NotNull final TaskFile taskFile, String fileName) { - StudyEditor.deleteGuardedBlocks(document); + StudyUtils.deleteGuardedBlocks(document); taskFile.setTrackChanges(false); clearDocument(document); Task task = taskFile.getTask(); @@ -167,14 +175,14 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction { @Override public void update(AnActionEvent event) { + EduUtils.enableAction(event, false); final Project project = event.getProject(); if (project != null) { - StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project); + StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); StudyState studyState = new StudyState(studyEditor); if (studyState.isValid()) { EduUtils.enableAction(event, true); } } - EduUtils.enableAction(event, false); } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java index 8bf70f564a7c..79b07c1453ed 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyRunAction.java @@ -5,6 +5,7 @@ import com.intellij.execution.RunContentExecutor; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessHandler; +import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; @@ -14,20 +15,29 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; +import com.jetbrains.edu.EduUtils; import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.courseFormat.TaskFile; +import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.courseFormat.UserTest; import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class StudyRunAction extends DumbAwareAction { private static final Logger LOG = Logger.getInstance(StudyRunAction.class.getName()); public static final String ACTION_ID = "StudyRunAction"; private ProcessHandler myHandler; + public StudyRunAction() { + super("Run File With Tests", "Run your code with tests", AllIcons.General.Run); + } + public void run(@NotNull final Project project) { if (myHandler != null && !myHandler.isProcessTerminated()) return; - Editor selectedEditor = StudyEditor.getSelectedEditor(project); + Editor selectedEditor = StudyUtils.getSelectedEditor(project); FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); assert selectedEditor != null; VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument()); @@ -79,4 +89,20 @@ public class StudyRunAction extends DumbAwareAction { run(project); } } + + @Override + public void update(AnActionEvent e) { + EduUtils.enableAction(e, false); + + final Project project = e.getProject(); + if (project != null) { + StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); + if (studyEditor != null) { + final List userTests = StudyTaskManager.getInstance(project).getUserTests(studyEditor.getTaskFile().getTask()); + if (!userTests.isEmpty()) { + EduUtils.enableAction(e, true); + } + } + } + } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java index ab3a25e10eef..a742ff0ae447 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyShowHintAction.java @@ -3,8 +3,10 @@ package com.jetbrains.edu.learning.actions; import com.intellij.codeInsight.documentation.DocumentationComponent; import com.intellij.codeInsight.documentation.DocumentationManager; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; @@ -18,10 +20,11 @@ import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.learning.StudyState; import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; -import com.jetbrains.edu.learning.editor.StudyEditor; import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + public class StudyShowHintAction extends DumbAwareAction { public static final String ACTION_ID = "ShowHintAction"; public static final String SHORTCUT = "ctrl pressed 7"; @@ -29,7 +32,7 @@ public class StudyShowHintAction extends DumbAwareAction { public static final String HINT_NOT_AVAILABLE = "There is no hint for this answer placeholder"; public StudyShowHintAction() { - super("Show hint", "Show hint", InteractiveLearningIcons.ShowHint); + super("Show hint (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Show hint", InteractiveLearningIcons.ShowHint); } public void actionPerformed(@NotNull AnActionEvent e) { @@ -45,7 +48,7 @@ public class StudyShowHintAction extends DumbAwareAction { if (course == null) { return; } - StudyState studyState = new StudyState(StudyEditor.getSelectedStudyEditor(project)); + StudyState studyState = new StudyState(StudyUtils.getSelectedStudyEditor(project)); if (!studyState.isValid()) { return; } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index 015a18ff227d..eaa828be292a 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -18,8 +18,10 @@ import com.jetbrains.edu.EduNames; import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.learning.StudyState; +import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.editor.StudyEditor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.TreePath; @@ -27,8 +29,12 @@ import java.util.Map; abstract public class StudyTaskNavigationAction extends DumbAwareAction { + public StudyTaskNavigationAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) { + super(text, description, icon); + } + public void navigateTask(@NotNull final Project project) { - StudyEditor studyEditor = StudyEditor.getSelectedStudyEditor(project); + StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); StudyState studyState = new StudyState(studyEditor); if (!studyState.isValid()) { return; @@ -39,7 +45,7 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction { JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(getNavigationFinishedMessage(), MessageType.INFO, null); Balloon balloon = balloonBuilder.createBalloon(); assert studyEditor != null; - balloon.showInCenterOf(getButton(studyEditor)); + balloon.show(StudyUtils.computeLocation(studyEditor.getEditor()), Balloon.Position.above); return; } for (VirtualFile file : FileEditorManager.getInstance(project).getOpenFiles()) { @@ -90,8 +96,6 @@ abstract public class StudyTaskNavigationAction extends DumbAwareAction { } } - protected abstract JButton getButton(@NotNull final StudyEditor selectedStudyEditor); - @Override public void actionPerformed(AnActionEvent e) { Project project = e.getProject(); diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java index 6a00f0e22122..add5910357f0 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/actions/StudyWindowNavigationAction.java @@ -9,7 +9,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.jetbrains.edu.courseFormat.AnswerPlaceholder; import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.learning.StudyUtils; -import com.jetbrains.edu.learning.editor.StudyEditor; import com.jetbrains.edu.learning.navigation.StudyNavigator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,7 +22,7 @@ abstract public class StudyWindowNavigationAction extends DumbAwareAction { } private void navigateToPlaceholder(@NotNull final Project project) { - final Editor selectedEditor = StudyEditor.getSelectedEditor(project); + final Editor selectedEditor = StudyUtils.getSelectedEditor(project); if (selectedEditor != null) { final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance(); final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument()); diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java index 90b9afd9b60a..ae5366a50970 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditor.java @@ -1,405 +1,38 @@ package com.jetbrains.edu.learning.editor; -import com.intellij.codeHighlighting.BackgroundEditorHighlighter; -import com.intellij.icons.AllIcons; -import com.intellij.ide.structureView.StructureViewBuilder; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.KeyboardShortcut; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.impl.DocumentImpl; -import com.intellij.openapi.fileEditor.*; -import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileEditor.impl.text.PsiAwareTextEditorImpl; import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider; -import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowId; -import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.pom.Navigatable; -import com.intellij.ui.BrowserHyperlinkListener; -import com.intellij.ui.HideableTitledPanel; -import com.intellij.ui.JBColor; -import com.intellij.util.ui.EmptyClipboardOwner; -import com.intellij.util.ui.UIUtil; import com.jetbrains.edu.EduDocumentListener; -import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.courseFormat.TaskFile; -import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; -import com.jetbrains.edu.learning.actions.*; -import com.jetbrains.edu.learning.courseFormat.UserTest; -import icons.InteractiveLearningIcons; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import javax.swing.text.MutableAttributeSet; -import javax.swing.text.StyleConstants; -import javax.swing.text.StyledDocument; -import java.awt.*; -import java.awt.datatransfer.StringSelection; -import java.awt.event.*; -import java.beans.PropertyChangeListener; import java.util.HashMap; -import java.util.List; import java.util.Map; /** * Implementation of StudyEditor which has panel with special buttons and task text * also @see {@link StudyFileEditorProvider} */ -public class StudyEditor implements TextEditor { - private static final String TASK_TEXT_HEADER = "Task Text"; - private final FileEditor myDefaultEditor; - private final JComponent myComponent; +public class StudyEditor extends PsiAwareTextEditorImpl { private final TaskFile myTaskFile; - private JButton myCheckButton; - private JButton myNextTaskButton; - private JButton myPrevTaskButton; - private JButton myRefreshButton; private static final Map myDocumentListeners = new HashMap(); - private final Project myProject; - - public JButton getCheckButton() { - return myCheckButton; - } - - public JButton getPrevTaskButton() { - return myPrevTaskButton; - } public TaskFile getTaskFile() { return myTaskFile; } - private static JButton addButton(@NotNull final JComponent parentComponent, @NotNull final String actionID, - @NotNull final Icon icon, @Nullable String defaultShortcutString) { - final AnAction action = ActionManager.getInstance().getAction(actionID); - String toolTipText = KeymapUtil.createTooltipText(action.getTemplatePresentation().getText(), action); - if (!toolTipText.contains("(") && defaultShortcutString != null) { - KeyboardShortcut shortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(defaultShortcutString), null); - toolTipText += " (" + KeymapUtil.getShortcutText(shortcut) + ")"; - } - final JButton newButton = new JButton(); - newButton.setToolTipText(toolTipText); - newButton.setIcon(icon); - newButton.setSize(new Dimension(icon.getIconWidth(), icon.getIconHeight())); - parentComponent.add(newButton); - return newButton; - } - public static void addDocumentListener(@NotNull final Document document, @NotNull final EduDocumentListener listener) { document.addDocumentListener(listener); myDocumentListeners.put(document, listener); } public StudyEditor(@NotNull final Project project, @NotNull final VirtualFile file) { - myProject = project; - myDefaultEditor = TextEditorProvider.getInstance().createEditor(myProject, file); - myComponent = myDefaultEditor.getComponent(); - final JPanel studyPanel = new JPanel(); - studyPanel.setLayout(new BoxLayout(studyPanel, BoxLayout.Y_AXIS)); + super(project, file, TextEditorProvider.getInstance()); myTaskFile = StudyUtils.getTaskFile(project, file); - if (myTaskFile != null) { - final Task currentTask = myTaskFile.getTask(); - final String taskText = currentTask.getText(); - //initializeTaskText(studyPanel, taskText); - final JPanel studyButtonPanel = new JPanel(new GridLayout(1, 2)); - final JPanel taskActionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - studyButtonPanel.add(taskActionsPanel); - studyButtonPanel.add(new JPanel()); - initializeButtons(taskActionsPanel, myTaskFile); - studyPanel.add(studyButtonPanel); - myComponent.add(studyPanel, BorderLayout.NORTH); - } - } - - class CopyListener extends MouseAdapter { - final JTextPane myTextPane; - - public CopyListener(@NotNull final JTextPane textPane) { - myTextPane = textPane; - } - - @Override - public void mouseReleased(MouseEvent e) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - final ToolWindow projectView = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW); - if (projectView == null) { - return; - } - final Component focusComponent = projectView.getComponent(); - IdeFocusManager.getInstance(myProject).requestFocus(focusComponent, true); - final String text = myTextPane.getSelectedText(); - if (text == null) { - return; - } - KeyAdapter keyAdapter = new KeyAdapter() { - @Override - public void keyPressed(KeyEvent ev) { - if (ev.getKeyCode() == KeyEvent.VK_C - && ev.getModifiers() == InputEvent.CTRL_MASK) { - final StringSelection selection = new StringSelection(text); - Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, EmptyClipboardOwner.INSTANCE); - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - IdeFocusManager.getInstance(myProject).requestFocus(myDefaultEditor.getComponent(), true); - } - }); - } - } - }; - focusComponent.addKeyListener(keyAdapter); - } - }); - } - } - - private void initializeTaskText(@NotNull final JPanel studyPanel, @Nullable final String taskText) { - final JTextPane taskTextPane = new JTextPane(); - taskTextPane.addMouseListener(new CopyListener(taskTextPane)); - taskTextPane.setContentType("text/html"); - taskTextPane.setEditable(false); - taskTextPane.setText(taskText); - taskTextPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE); - final EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme(); - int fontSize = editorColorsScheme.getEditorFontSize(); - final String fontName = editorColorsScheme.getEditorFontName(); - setJTextPaneFont(taskTextPane, new Font(fontName, Font.PLAIN, fontSize)); - taskTextPane.setBackground(UIUtil.getPanelBackground()); - taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100)); - final HideableTitledPanel taskTextPanel = new HideableTitledPanel(TASK_TEXT_HEADER, taskTextPane, true); - taskTextPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); - studyPanel.add(taskTextPanel); - } - - private static void setJTextPaneFont(@NotNull final JTextPane textPane, @NotNull final Font font) { - final MutableAttributeSet attrs = textPane.getInputAttributes(); - StyleConstants.setFontFamily(attrs, font.getFamily()); - StyleConstants.setFontSize(attrs, font.getSize()); - StyleConstants.setItalic(attrs, (font.getStyle() & Font.ITALIC) != 0); - StyleConstants.setBold(attrs, (font.getStyle() & Font.BOLD) != 0); - StyleConstants.setForeground(attrs, JBColor.BLACK); - StyledDocument doc = textPane.getStyledDocument(); - doc.setCharacterAttributes(0, doc.getLength() + 1, attrs, false); - } - - private void initializeButtons(@NotNull final JPanel taskActionsPanel, @NotNull final TaskFile taskFile) { - myCheckButton = addButton(taskActionsPanel, StudyCheckAction.ACTION_ID, InteractiveLearningIcons.Resolve, StudyCheckAction.SHORTCUT); - myPrevTaskButton = addButton(taskActionsPanel, StudyPreviousStudyTaskAction.ACTION_ID, InteractiveLearningIcons.Prev, StudyPreviousStudyTaskAction.SHORTCUT); - myNextTaskButton = addButton(taskActionsPanel, StudyNextStudyTaskAction.ACTION_ID, AllIcons.Actions.Forward, StudyNextStudyTaskAction.SHORTCUT); - myRefreshButton = addButton(taskActionsPanel, StudyRefreshTaskFileAction.ACTION_ID, AllIcons.Actions.Refresh, StudyRefreshTaskFileAction.SHORTCUT); - final JButton myShowHintButton = addButton(taskActionsPanel, StudyShowHintAction.ACTION_ID, InteractiveLearningIcons.ShowHint, StudyShowHintAction.SHORTCUT); - final List userTests = StudyTaskManager.getInstance(myProject).getUserTests(taskFile.getTask()); - if (!userTests.isEmpty()) { - final JButton runButton = addButton(taskActionsPanel, StudyRunAction.ACTION_ID, AllIcons.General.Run, null); - runButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyRunAction studyRunAction = (StudyRunAction)ActionManager.getInstance().getAction("StudyRunAction"); - studyRunAction.run(myProject); - } - }); - final JButton watchInputButton = addButton(taskActionsPanel, "WatchInputAction", InteractiveLearningIcons.WatchInput, null); - watchInputButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyEditInputAction studyEditInputAction = - (StudyEditInputAction)ActionManager.getInstance().getAction("WatchInputAction"); - studyEditInputAction.showInput(myProject); - } - }); - } - initializeButtonActions(myShowHintButton); - } - - protected void initializeButtonActions(JButton myShowHintButton) { - myCheckButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyCheckAction studyCheckAction = (StudyCheckAction)ActionManager.getInstance().getAction("CheckAction"); - studyCheckAction.check(myProject); - } - }); - - myNextTaskButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyNextStudyTaskAction studyNextTaskAction = - (StudyNextStudyTaskAction)ActionManager.getInstance().getAction("NextTaskAction"); - studyNextTaskAction.navigateTask(myProject); - } - }); - myPrevTaskButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyPreviousStudyTaskAction - prevTaskAction = (StudyPreviousStudyTaskAction)ActionManager.getInstance().getAction("PreviousTaskAction"); - prevTaskAction.navigateTask(myProject); - } - }); - myRefreshButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyRefreshTaskFileAction.refresh(myProject); - } - }); - - myShowHintButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - StudyShowHintAction.showHint(myProject); - } - }); - } - - public JButton getNextTaskButton() { - return myNextTaskButton; - } - - public JButton getRefreshButton() { - return myRefreshButton; - } - - private FileEditor getDefaultEditor() { - return myDefaultEditor; - } - - @NotNull - @Override - public JComponent getComponent() { - return myComponent; - } - - @Nullable - @Override - public JComponent getPreferredFocusedComponent() { - return myDefaultEditor.getPreferredFocusedComponent(); - } - - @NotNull - @Override - public String getName() { - return "Study Editor"; - } - - @NotNull - @Override - public FileEditorState getState(@NotNull FileEditorStateLevel level) { - return myDefaultEditor.getState(level); - } - - @Override - public void setState(@NotNull FileEditorState state) { - myDefaultEditor.setState(state); - } - - @Override - public boolean isModified() { - return myDefaultEditor.isModified(); - } - - @Override - public boolean isValid() { - return myDefaultEditor.isValid(); - } - - @Override - public void selectNotify() { - myDefaultEditor.selectNotify(); - } - - @Override - public void deselectNotify() { - myDefaultEditor.deselectNotify(); - } - - @Override - public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) { - myDefaultEditor.addPropertyChangeListener(listener); - } - - @Override - public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) { - myDefaultEditor.removePropertyChangeListener(listener); - } - - @Nullable - @Override - public BackgroundEditorHighlighter getBackgroundHighlighter() { - return myDefaultEditor.getBackgroundHighlighter(); - } - - @Nullable - @Override - public FileEditorLocation getCurrentLocation() { - return myDefaultEditor.getCurrentLocation(); - } - - @Nullable - @Override - public StructureViewBuilder getStructureViewBuilder() { - return myDefaultEditor.getStructureViewBuilder(); - } - - @Override - public void dispose() { - Disposer.dispose(myDefaultEditor); - } - - @Nullable - @Override - public T getUserData(@NotNull Key key) { - return myDefaultEditor.getUserData(key); - } - - @Override - public void putUserData(@NotNull Key key, @Nullable T value) { - myDefaultEditor.putUserData(key, value); - } - - - @Nullable - public static StudyEditor getSelectedStudyEditor(@NotNull final Project project) { - try { - final FileEditor fileEditor = FileEditorManagerEx.getInstanceEx(project).getSplitters().getCurrentWindow(). - getSelectedEditor().getSelectedEditorWithProvider().getFirst(); - if (fileEditor instanceof StudyEditor) { - return (StudyEditor)fileEditor; - } - } - catch (Exception e) { - return null; - } - return null; - } - - @Nullable - public static Editor getSelectedEditor(@NotNull final Project project) { - final StudyEditor studyEditor = getSelectedStudyEditor(project); - if (studyEditor != null) { - FileEditor defaultEditor = studyEditor.getDefaultEditor(); - if (defaultEditor instanceof PsiAwareTextEditorImpl) { - return ((PsiAwareTextEditorImpl)defaultEditor).getEditor(); - } - } - return null; } public static void removeListener(Document document) { @@ -409,48 +42,4 @@ public class StudyEditor implements TextEditor { } myDocumentListeners.remove(document); } - - @NotNull - @Override - public Editor getEditor() { - if (myDefaultEditor instanceof TextEditor) { - return ((TextEditor)myDefaultEditor).getEditor(); - } - return EditorFactory.getInstance().createViewer(new DocumentImpl(""), myProject); - } - - @Override - public boolean canNavigateTo(@NotNull Navigatable navigatable) { - if (myDefaultEditor instanceof TextEditor) { - ((TextEditor)myDefaultEditor).canNavigateTo(navigatable); - } - return false; - } - - @Override - public void navigateTo(@NotNull Navigatable navigatable) { - if (myDefaultEditor instanceof TextEditor) { - ((TextEditor)myDefaultEditor).navigateTo(navigatable); - } - } - - public static void deleteGuardedBlocks(@NotNull final Document document) { - if (document instanceof DocumentImpl) { - final DocumentImpl documentImpl = (DocumentImpl)document; - List blocks = documentImpl.getGuardedBlocks(); - for (final RangeMarker block : blocks) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - document.removeGuardedBlock(block); - } - }); - } - }); - } - } - } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java index 1a04083a612e..66b06933e321 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/editor/StudyEditorFactoryListener.java @@ -9,11 +9,14 @@ import com.intellij.openapi.editor.event.EditorFactoryListener; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.problems.WolfTheProblemSolver; import com.jetbrains.edu.EduDocumentListener; import com.jetbrains.edu.courseFormat.TaskFile; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.navigation.StudyNavigator; +import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import org.jetbrains.annotations.NotNull; @@ -43,6 +46,13 @@ public class StudyEditorFactoryListener implements EditorFactoryListener { StudyEditor.addDocumentListener(document, new EduDocumentListener(taskFile)); WolfTheProblemSolver.getInstance(project).clearProblems(openedFile); StudyUtils.drawAllWindows(editor, taskFile); + + final ToolWindow studyToolWindow = ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); + if (studyToolWindow != null) { + StudyUtils.updateStudyToolWindow(project); + studyToolWindow.show(null); + } + } } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java index 46ac007e4dc7..4895bc04faf7 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyCondition.java @@ -1,26 +1,15 @@ package com.jetbrains.edu.learning.ui; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; -import com.jetbrains.edu.learning.StudyTaskManager; /** * author: liana * data: 7/29/14. */ public class StudyCondition implements Condition, DumbAware { - public static boolean VALUE = false; @Override public boolean value(Object o) { - if (o instanceof Project) { - Project project = (Project) o; - StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - if (taskManager.getCourse() != null) { - //noinspection AssignmentToStaticFieldFromInstanceMethod - VALUE = true; - } - } return false; } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java new file mode 100644 index 000000000000..f31cfa98e28d --- /dev/null +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.edu.learning.ui; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.ActionToolbar; +import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.SimpleToolWindowPanel; +import com.intellij.ui.BrowserHyperlinkListener; +import com.intellij.util.ui.JBUI; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.editor.StudyEditor; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; + +public class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable { + + private final JPanel myToolbarPanel; + + public StudyToolWindow(final Project project) { + super(true, true); + myToolbarPanel = createToolbarPanel(); + setToolbar(myToolbarPanel); + + final StudyEditor studyEditor = StudyUtils.getSelectedStudyEditor(project); + if (studyEditor == null) return; + Task task = studyEditor.getTaskFile().getTask(); + + if (task != null) { + final String taskText = task.getText(); + + final JTextPane taskTextPane = new JTextPane(); + taskTextPane.setContentType("text/html"); + taskTextPane.setEditable(false); + taskTextPane.setText(taskText); + taskTextPane.addHyperlinkListener(BrowserHyperlinkListener.INSTANCE); + taskTextPane.setBackground(EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground()); + taskTextPane.setBorder(new EmptyBorder(15, 20, 0, 100)); + setContent(taskTextPane); + } + } + + public void dispose() { + } + + private static JPanel createToolbarPanel() { + final DefaultActionGroup group = new DefaultActionGroup(); + group.add(new StudyCheckAction()); + group.add(new StudyPreviousStudyTaskAction()); + group.add(new StudyNextStudyTaskAction()); + group.add(new StudyRefreshTaskFileAction()); + group.add(new StudyShowHintAction()); + + group.add(new StudyRunAction()); + group.add(new StudyEditInputAction()); + + final ActionToolbar actionToolBar = ActionManager.getInstance().createActionToolbar("Study", group, true); + return JBUI.Panels.simplePanel(actionToolBar.getComponent()); + } + +} diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java index 0539c68a9965..4522064be221 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java @@ -2,90 +2,31 @@ package com.jetbrains.edu.learning.ui; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; -import com.intellij.util.ui.UIUtil; +import com.intellij.ui.content.ContentManager; import com.jetbrains.edu.courseFormat.Course; -import com.jetbrains.edu.courseFormat.Lesson; -import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.learning.StudyTaskManager; -import com.jetbrains.edu.learning.courseFormat.StudyStatus; import org.jetbrains.annotations.NotNull; -import javax.swing.*; -import java.awt.*; -import java.util.List; - public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware { - public static final String STUDY_TOOL_WINDOW = "Course Description"; + public static final String STUDY_TOOL_WINDOW = "Task Description"; @Override public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) { - JPanel contentPanel = new JPanel(); StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - if (taskManager.getCourse() != null) { - contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)); - contentPanel.add(Box.createRigidArea(new Dimension(10, 0))); + final Course course = taskManager.getCourse(); + if (course != null) { + final StudyToolWindow studyToolWindow = new StudyToolWindow(project); + final ContentManager contentManager = toolWindow.getContentManager(); + final Content content = contentManager.getFactory().createContent(studyToolWindow, null, false); + contentManager.addContent(content); + Disposer.register(project, studyToolWindow); - Course course = taskManager.getCourse(); - if (course == null) { - return; - } - String courseName = UIUtil.toHtml("

" + course.getName() + "

", 10); - String description = UIUtil.toHtml(course.getDescription(), 5); - String authorLabel = UIUtil.toHtml("Author: " + Course.getAuthorsString(course.getAuthors()), 5); - contentPanel.add(new JLabel(courseName)); - contentPanel.add(new JLabel(authorLabel)); - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - contentPanel.add(new JLabel(description)); - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - int taskNum = 0; - int taskSolved = 0; - int lessonsCompleted = 0; - List lessons = course.getLessons(); - for (Lesson lesson : lessons) { - StudyStatus status = taskManager.getStatus(lesson); - if (status == StudyStatus.Solved) { - lessonsCompleted++; - } - taskNum += lesson.getTaskList().size(); - taskSolved += getSolvedTasks(lesson, taskManager); - } - String completedLessons = String.format("%d of %d lessons completed", lessonsCompleted, course.getLessons().size()); - String completedTasks = String.format("%d of %d tasks completed", taskSolved, taskNum); - String tasksLeft = String.format("%d of %d tasks left", taskNum - taskSolved, taskNum); - contentPanel.add(Box.createVerticalStrut(10)); - addStatistics(completedLessons, contentPanel); - addStatistics(completedTasks, contentPanel); - - double percent = (taskSolved * 100.0) / taskNum; - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - StudyProgressBar studyProgressBar = new StudyProgressBar(percent / 100, 40, 10); - contentPanel.add(studyProgressBar); - addStatistics(tasksLeft, contentPanel); - ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); - Content content = contentFactory.createContent(contentPanel, "", true); - toolWindow.getContentManager().addContent(content); } } - private static int getSolvedTasks(@NotNull final Lesson lesson, StudyTaskManager taskManager) { - int solved = 0; - for (Task task : lesson.getTaskList()) { - if (taskManager.getStatus(task) == StudyStatus.Solved) { - solved += 1; - } - } - return solved; - } - - private static void addStatistics(String statistics, JPanel contentPanel) { - String labelText = UIUtil.toHtml(statistics, 5); - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel statisticLabel = new JLabel(labelText); - contentPanel.add(statisticLabel); - } }