diff --git a/python/educational/interactive-learning/resources/META-INF/plugin.xml b/python/educational/interactive-learning/resources/META-INF/plugin.xml index 7aa96b77e3a9..0c112e2e4bea 100644 --- a/python/educational/interactive-learning/resources/META-INF/plugin.xml +++ b/python/educational/interactive-learning/resources/META-INF/plugin.xml @@ -22,8 +22,8 @@ - com.jetbrains.edu.learning.StudyTaskManager - com.jetbrains.edu.learning.StudyTaskManager + com.jetbrains.edu.learning.StudyProjectComponent + com.jetbrains.edu.learning.StudyProjectComponent @@ -72,5 +72,7 @@ serviceImplementation="com.jetbrains.edu.learning.StudyInstructionPainter" overrides="true"/> + \ No newline at end of file diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectComponent.java new file mode 100644 index 000000000000..029bb23b1351 --- /dev/null +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -0,0 +1,314 @@ +package com.jetbrains.edu.learning; + +import com.intellij.ide.ui.UISettings; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.ex.AnActionListener; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ProjectComponent; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.ModuleServiceManager; +import com.intellij.openapi.project.DumbAwareRunnable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.startup.StartupManager; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileAdapter; +import com.intellij.openapi.vfs.VirtualFileEvent; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.wm.*; +import com.jetbrains.edu.StudyNames; +import com.jetbrains.edu.courseFormat.Course; +import com.jetbrains.edu.courseFormat.Lesson; +import com.jetbrains.edu.courseFormat.Task; +import com.jetbrains.edu.courseFormat.TaskFile; +import com.jetbrains.edu.learning.actions.*; +import com.jetbrains.edu.learning.courseGeneration.StudyGenerator; +import com.jetbrains.edu.learning.editor.StudyEditorFactoryListener; +import com.jetbrains.edu.learning.ui.StudyCondition; +import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class StudyProjectComponent implements ProjectComponent { + private static final Logger LOG = Logger.getInstance(StudyProjectComponent.class.getName()); + private static Map myDeletedShortcuts = new HashMap(); + private final Project myProject; + + private FileCreatedByUserListener myListener; + + private StudyProjectComponent(@NotNull final Project project) { + myProject = project; + } + + @Override + public void projectOpened() { + final Course course = StudyTaskManager.getInstance(myProject).getCourse(); + if (course != null && !course.isUpToDate()) { + course.setUpToDate(true); + updateCourse(); + } + + registerStudyToolwindow(course); + ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() { + @Override + public void run() { + ApplicationManager.getApplication().runWriteAction(new DumbAwareRunnable() { + @Override + public void run() { + if (course != null) { + moveFocusToEditor(); + UISettings.getInstance().HIDE_TOOL_STRIPES = false; + UISettings.getInstance().fireUISettingsChanged(); + registerShortcuts(); + } + } + }); + } + }); + } + + public void registerStudyToolwindow(@Nullable final Course course) { + if (course != null) { + final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); + registerToolWindow(toolWindowManager); + final ToolWindow studyToolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); + if (studyToolWindow != null) { + StudyUtils.updateStudyToolWindow(myProject); + studyToolWindow.show(null); + } + } + } + + private void moveFocusToEditor() { + StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() { + @Override + public void run() { + ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW).show(new Runnable() { + @Override + public void run() { + FileEditor[] editors = FileEditorManager.getInstance(myProject).getSelectedEditors(); + if (editors.length > 0) { + final JComponent focusedComponent = editors[0].getPreferredFocusedComponent(); + if (focusedComponent != null) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true); + } + }); + } + } + } + }); + } + }); + } + + private static void registerShortcuts() { + addShortcut(StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.ACTION_ID, false); + addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID, false); + addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID, false); + addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID, true); + addShortcut(StudyCheckAction.SHORTCUT, StudyCheckAction.ACTION_ID, false); + addShortcut(StudyNextStudyTaskAction.SHORTCUT, StudyNextStudyTaskAction.ACTION_ID, false); + addShortcut(StudyPreviousStudyTaskAction.SHORTCUT, StudyPreviousStudyTaskAction.ACTION_ID, false); + addShortcut(StudyRefreshTaskFileAction.SHORTCUT, StudyRefreshTaskFileAction.ACTION_ID, false); + } + + private void registerToolWindow(@NotNull final ToolWindowManager toolWindowManager) { + try { + Method method = toolWindowManager.getClass().getDeclaredMethod("registerToolWindow", String.class, + JComponent.class, + ToolWindowAnchor.class, + boolean.class, boolean.class, boolean.class); + method.setAccessible(true); + method.invoke(toolWindowManager, StudyToolWindowFactory.STUDY_TOOL_WINDOW, null, ToolWindowAnchor.LEFT, true, true, true); + } + catch (Exception e) { + final ToolWindow toolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); + if (toolWindow == null) { + toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, myProject, true); + } + } + } + + private void updateCourse() { + final Course course = StudyTaskManager.getInstance(myProject).getCourse(); + if (course == null) { + return; + } + final File resourceDirectory = new File(course.getCourseDirectory()); + if (!resourceDirectory.exists()) { + return; + } + StudyLanguageManager manager = StudyUtils.getLanguageManager(course); + if (manager == null) { + LOG.info("Study Language Manager is null for " + course.getLanguageById().getDisplayName()); + return; + } + final File[] files = resourceDirectory.listFiles(); + if (files == null) return; + for (File file : files) { + String testHelper = manager.getTestHelperFileName(); + if (file.getName().equals(testHelper)) { + copyFile(file, new File(myProject.getBasePath(), testHelper)); + } + if (file.getName().startsWith(StudyNames.LESSON)) { + final File[] tasks = file.listFiles(); + if (tasks == null) continue; + for (File task : tasks) { + final File taskDescr = new File(task, StudyNames.TASK_HTML); + String testFileName = manager.getTestFileName(); + final File taskTests = new File(task, testFileName); + copyFile(taskDescr, new File(new File(new File(myProject.getBasePath(), file.getName()), task.getName()), StudyNames.TASK_HTML)); + copyFile(taskTests, new File(new File(new File(myProject.getBasePath(), file.getName()), task.getName()), + testFileName)); + } + } + } + + final Notification notification = + new Notification("Update.course", "Course update", "Current course is synchronized", NotificationType.INFORMATION); + notification.notify(myProject); + } + + private static void copyFile(@NotNull final File from, @NotNull final File to) { + if (from.exists()) { + try { + FileUtil.copy(from, to); + } + catch (IOException e) { + LOG.warn("Failed to copy " + from.getName()); + } + } + } + + private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString, boolean isAdditional) { + Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); + Shortcut[] shortcuts = keymap.getShortcuts(actionIdString); + if (shortcuts.length > 0 && !isAdditional) { + return; + } + Shortcut studyActionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcutString), null); + String[] actionsIds = keymap.getActionIds(studyActionShortcut); + for (String actionId : actionsIds) { + myDeletedShortcuts.put(actionId, shortcutString); + keymap.removeShortcut(actionId, studyActionShortcut); + } + keymap.addShortcut(actionIdString, studyActionShortcut); + } + + @Override + public void projectClosed() { + //noinspection AssignmentToStaticFieldFromInstanceMethod + StudyCondition.VALUE = false; + final Course course = StudyTaskManager.getInstance(myProject).getCourse(); + if (course != null) { + ToolWindowManager.getInstance(myProject).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager() + .removeAllContents(false); + if (!myDeletedShortcuts.isEmpty()) { + for (Map.Entry shortcut : myDeletedShortcuts.entrySet()) { + final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); + final Shortcut actionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcut.getValue()), null); + keymap.addShortcut(shortcut.getKey(), actionShortcut); + } + } + } + } + + @Override + public void initComponent() { + EditorFactory.getInstance().addEditorFactoryListener(new StudyEditorFactoryListener(), myProject); + ActionManager.getInstance().addAnActionListener(new AnActionListener() { + @Override + public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) { + AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null); + for (AnAction newAction : newGroupActions) { + if (newAction == action) { + myListener = new FileCreatedByUserListener(); + VirtualFileManager.getInstance().addVirtualFileListener(myListener); + break; + } + } + } + + @Override + public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) { + AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null); + for (AnAction newAction : newGroupActions) { + if (newAction == action) { + VirtualFileManager.getInstance().removeVirtualFileListener(myListener); + } + } + } + + @Override + public void beforeEditorTyping(char c, DataContext dataContext) { + + } + }); + } + + @Override + public void disposeComponent() { + } + + @NotNull + @Override + public String getComponentName() { + return "StudyTaskManager"; + } + + public static StudyProjectComponent getInstance(@NotNull final Project project) { + final Module module = ModuleManager.getInstance(project).getModules()[0]; + return ModuleServiceManager.getService(module, StudyProjectComponent.class); + } + private class FileCreatedByUserListener extends VirtualFileAdapter { + @Override + public void fileCreated(@NotNull VirtualFileEvent event) { + final VirtualFile createdFile = event.getFile(); + final VirtualFile taskDir = createdFile.getParent(); + final Course course = StudyTaskManager.getInstance(myProject).getCourse(); + if (taskDir != null && taskDir.getName().contains(StudyNames.TASK_DIR)) { + int taskIndex = StudyUtils.getIndex(taskDir.getName(), StudyNames.TASK_DIR); + final VirtualFile lessonDir = taskDir.getParent(); + if (lessonDir != null && lessonDir.getName().contains(StudyNames.LESSON_DIR)) { + int lessonIndex = StudyUtils.getIndex(lessonDir.getName(), StudyNames.LESSON_DIR); + if (course != null) { + List lessons = course.getLessons(); + if (StudyUtils.indexIsValid(lessonIndex, lessons)) { + final Lesson lesson = lessons.get(lessonIndex); + final List tasks = lesson.getTaskList(); + if (StudyUtils.indexIsValid(taskIndex, tasks)) { + final Task task = tasks.get(taskIndex); + final TaskFile taskFile = new TaskFile(); + StudyGenerator.initTaskFile(taskFile, task, false); + taskFile.setUserCreated(true); + task.getTaskFiles().put(createdFile.getName(), taskFile); + } + } + } + } + } + } + } + +} diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java index 353e80430b05..0a1dbed80f2f 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java @@ -1,54 +1,20 @@ package com.jetbrains.edu.learning; -import com.intellij.ide.ui.UISettings; -import com.intellij.notification.Notification; -import com.intellij.notification.NotificationType; -import com.intellij.openapi.actionSystem.*; -import com.intellij.openapi.actionSystem.ex.AnActionListener; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.*; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.fileEditor.FileEditor; -import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleServiceManager; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; -import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileAdapter; -import com.intellij.openapi.vfs.VirtualFileEvent; -import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.openapi.wm.*; -import com.intellij.util.xmlb.XmlSerializer; -import com.jetbrains.edu.StudyNames; +import com.intellij.util.xmlb.XmlSerializerUtil; import com.jetbrains.edu.courseFormat.Course; -import com.jetbrains.edu.courseFormat.Lesson; -import com.jetbrains.edu.courseFormat.Task; -import com.jetbrains.edu.courseFormat.TaskFile; -import com.jetbrains.edu.learning.actions.*; import com.jetbrains.edu.learning.courseGeneration.StudyGenerator; -import com.jetbrains.edu.learning.editor.StudyEditorFactoryListener; -import com.jetbrains.edu.learning.ui.StudyCondition; -import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; -import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * Implementation of class which contains all the information * about study in context of current project @@ -63,21 +29,14 @@ import java.util.Map; scheme = StorageScheme.DIRECTORY_BASED )} ) -public class StudyTaskManager implements ProjectComponent, PersistentStateComponent, DumbAware { - private static final Logger LOG = Logger.getInstance(StudyTaskManager.class.getName()); - public static final String COURSE_ELEMENT = "courseElement"; - private static Map myDeletedShortcuts = new HashMap(); - private final Project myProject; - private Course myCourse; - private FileCreatedByUserListener myListener; - +public class StudyTaskManager implements PersistentStateComponent, DumbAware { + public Course myCourse; public void setCourse(@NotNull final Course course) { myCourse = course; } - private StudyTaskManager(@NotNull final Project project) { - myProject = project; + private StudyTaskManager() { } @Nullable @@ -87,265 +46,21 @@ public class StudyTaskManager implements ProjectComponent, PersistentStateCompon @Nullable @Override - public Element getState() { - Element el = new Element("taskManager"); - if (myCourse != null) { - Element courseElement = new Element(COURSE_ELEMENT); - XmlSerializer.serializeInto(myCourse, courseElement); - el.addContent(courseElement); - } - return el; + public StudyTaskManager getState() { + return this; } @Override - public void loadState(Element el) { - myCourse = XmlSerializer.deserialize(el.getChild(COURSE_ELEMENT), Course.class); + public void loadState(StudyTaskManager state) { + XmlSerializerUtil.copyBean(state, this); if (myCourse != null) { StudyGenerator.initCourse(myCourse, true); } } - @Override - public void projectOpened() { - if (myCourse != null && !myCourse.isUpToDate()) { - myCourse.setUpToDate(true); - updateCourse(); - } - ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new DumbAwareRunnable() { - @Override - public void run() { - if (myCourse != null) { - moveFocusToEditor(); - UISettings.getInstance().HIDE_TOOL_STRIPES = false; - UISettings.getInstance().fireUISettingsChanged(); - final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); - registerToolWindow(toolWindowManager); - final ToolWindow studyToolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); - if (studyToolWindow != null) { - StudyUtils.updateStudyToolWindow(myProject); - studyToolWindow.show(null); - } - registerShortcuts(); - } - } - }); - } - }); - } - - private void moveFocusToEditor() { - StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new Runnable() { - @Override - public void run() { - ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PROJECT_VIEW).show(new Runnable() { - @Override - public void run() { - FileEditor[] editors = FileEditorManager.getInstance(myProject).getSelectedEditors(); - if (editors.length > 0) { - final JComponent focusedComponent = editors[0].getPreferredFocusedComponent(); - if (focusedComponent != null) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - IdeFocusManager.getInstance(myProject).requestFocus(focusedComponent, true); - } - }); - } - } - } - }); - } - }); - } - - private static void registerShortcuts() { - addShortcut(StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.ACTION_ID, false); - addShortcut(StudyPrevWindowAction.SHORTCUT, StudyPrevWindowAction.ACTION_ID, false); - addShortcut(StudyShowHintAction.SHORTCUT, StudyShowHintAction.ACTION_ID, false); - addShortcut(StudyNextWindowAction.SHORTCUT2, StudyNextWindowAction.ACTION_ID, true); - addShortcut(StudyCheckAction.SHORTCUT, StudyCheckAction.ACTION_ID, false); - addShortcut(StudyNextStudyTaskAction.SHORTCUT, StudyNextStudyTaskAction.ACTION_ID, false); - addShortcut(StudyPreviousStudyTaskAction.SHORTCUT, StudyPreviousStudyTaskAction.ACTION_ID, false); - addShortcut(StudyRefreshTaskFileAction.SHORTCUT, StudyRefreshTaskFileAction.ACTION_ID, false); - } - - private void registerToolWindow(@NotNull final ToolWindowManager toolWindowManager) { - try { - Method method = toolWindowManager.getClass().getDeclaredMethod("registerToolWindow", String.class, - JComponent.class, - ToolWindowAnchor.class, - boolean.class, boolean.class, boolean.class); - method.setAccessible(true); - method.invoke(toolWindowManager, StudyToolWindowFactory.STUDY_TOOL_WINDOW, null, ToolWindowAnchor.LEFT, true, true, true); - } - catch (Exception e) { - final ToolWindow toolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); - if (toolWindow == null) { - toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, myProject, true); - } - } - } - - private void updateCourse() { - if (myCourse == null) { - return; - } - final File resourceDirectory = new File(myCourse.getCourseDirectory()); - if (!resourceDirectory.exists()) { - return; - } - StudyLanguageManager manager = StudyUtils.getLanguageManager(myCourse); - if (manager == null) { - LOG.info("Study Language Manager is null for " + myCourse.getLanguageById().getDisplayName()); - return; - } - final File[] files = resourceDirectory.listFiles(); - if (files == null) return; - for (File file : files) { - String testHelper = manager.getTestHelperFileName(); - if (file.getName().equals(testHelper)) { - copyFile(file, new File(myProject.getBasePath(), testHelper)); - } - if (file.getName().startsWith(StudyNames.LESSON)) { - final File[] tasks = file.listFiles(); - if (tasks == null) continue; - for (File task : tasks) { - final File taskDescr = new File(task, StudyNames.TASK_HTML); - String testFileName = manager.getTestFileName(); - final File taskTests = new File(task, testFileName); - copyFile(taskDescr, new File(new File(new File(myProject.getBasePath(), file.getName()), task.getName()), StudyNames.TASK_HTML)); - copyFile(taskTests, new File(new File(new File(myProject.getBasePath(), file.getName()), task.getName()), - testFileName)); - } - } - } - - final Notification notification = - new Notification("Update.course", "Course update", "Current course is synchronized", NotificationType.INFORMATION); - notification.notify(myProject); - } - - private static void copyFile(@NotNull final File from, @NotNull final File to) { - if (from.exists()) { - try { - FileUtil.copy(from, to); - } - catch (IOException e) { - LOG.warn("Failed to copy " + from.getName()); - } - } - } - - private static void addShortcut(@NotNull final String shortcutString, @NotNull final String actionIdString, boolean isAdditional) { - Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); - Shortcut[] shortcuts = keymap.getShortcuts(actionIdString); - if (shortcuts.length > 0 && !isAdditional) { - return; - } - Shortcut studyActionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcutString), null); - String[] actionsIds = keymap.getActionIds(studyActionShortcut); - for (String actionId : actionsIds) { - myDeletedShortcuts.put(actionId, shortcutString); - keymap.removeShortcut(actionId, studyActionShortcut); - } - keymap.addShortcut(actionIdString, studyActionShortcut); - } - - @Override - public void projectClosed() { - //noinspection AssignmentToStaticFieldFromInstanceMethod - StudyCondition.VALUE = false; - if (myCourse != null) { - ToolWindowManager.getInstance(myProject).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager() - .removeAllContents(false); - if (!myDeletedShortcuts.isEmpty()) { - for (Map.Entry shortcut : myDeletedShortcuts.entrySet()) { - final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); - final Shortcut actionShortcut = new KeyboardShortcut(KeyStroke.getKeyStroke(shortcut.getValue()), null); - keymap.addShortcut(shortcut.getKey(), actionShortcut); - } - } - } - } - - @Override - public void initComponent() { - EditorFactory.getInstance().addEditorFactoryListener(new StudyEditorFactoryListener(), myProject); - ActionManager.getInstance().addAnActionListener(new AnActionListener() { - @Override - public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) { - AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null); - for (AnAction newAction : newGroupActions) { - if (newAction == action) { - myListener = new FileCreatedByUserListener(); - VirtualFileManager.getInstance().addVirtualFileListener(myListener); - break; - } - } - } - - @Override - public void afterActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) { - AnAction[] newGroupActions = ((ActionGroup)ActionManager.getInstance().getAction("NewGroup")).getChildren(null); - for (AnAction newAction : newGroupActions) { - if (newAction == action) { - VirtualFileManager.getInstance().removeVirtualFileListener(myListener); - } - } - } - - @Override - public void beforeEditorTyping(char c, DataContext dataContext) { - - } - }); - } - - @Override - public void disposeComponent() { - } - - @NotNull - @Override - public String getComponentName() { - return "StudyTaskManager"; - } - public static StudyTaskManager getInstance(@NotNull final Project project) { final Module module = ModuleManager.getInstance(project).getModules()[0]; return ModuleServiceManager.getService(module, StudyTaskManager.class); } - private class FileCreatedByUserListener extends VirtualFileAdapter { - @Override - public void fileCreated(@NotNull VirtualFileEvent event) { - final VirtualFile createdFile = event.getFile(); - final VirtualFile taskDir = createdFile.getParent(); - if (taskDir != null && taskDir.getName().contains(StudyNames.TASK_DIR)) { - int taskIndex = StudyUtils.getIndex(taskDir.getName(), StudyNames.TASK_DIR); - final VirtualFile lessonDir = taskDir.getParent(); - if (lessonDir != null && lessonDir.getName().contains(StudyNames.LESSON_DIR)) { - int lessonIndex = StudyUtils.getIndex(lessonDir.getName(), StudyNames.LESSON_DIR); - if (myCourse != null) { - List lessons = myCourse.getLessons(); - if (StudyUtils.indexIsValid(lessonIndex, lessons)) { - final Lesson lesson = lessons.get(lessonIndex); - final List tasks = lesson.getTaskList(); - if (StudyUtils.indexIsValid(taskIndex, tasks)) { - final Task task = tasks.get(taskIndex); - final TaskFile taskFile = new TaskFile(); - StudyGenerator.initTaskFile(taskFile, task, false); - taskFile.setUserCreated(true); - task.getTaskFiles().put(createdFile.getName(), taskFile); - } - } - } - } - } - } - } - } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java index 9edf03edfdbf..c760ea735379 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java @@ -1,6 +1,5 @@ package com.jetbrains.edu.learning.courseGeneration; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; @@ -102,13 +101,7 @@ public class StudyGenerator { */ public static void createCourse(@NotNull final Course course, @NotNull final VirtualFile baseDir, @NotNull final File resourceRoot, @NotNull final Project project) { - ApplicationManager.getApplication().invokeLater( - new Runnable() { - @Override - public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { + try { final List lessons = course.getLessons(); for (int i = 0; i < lessons.size(); i++) { @@ -116,7 +109,7 @@ public class StudyGenerator { lesson.setIndex(i); createLesson(lesson, baseDir, resourceRoot, project); } - baseDir.createChildDirectory(this, StudyNames.SANDBOX_DIR); + baseDir.createChildDirectory(project, StudyNames.SANDBOX_DIR); File[] files = resourceRoot.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { @@ -130,10 +123,6 @@ public class StudyGenerator { catch (IOException e) { LOG.error(e); } - } - }); - } - }); } /** diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java index 69d9d499e234..264181547101 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java @@ -4,23 +4,18 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.intellij.facet.ui.ValidationResult; import com.intellij.ide.projectView.ProjectView; -import com.intellij.ide.projectView.impl.AbstractProjectViewPane; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl; -import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; -import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.containers.ContainerUtil; @@ -28,14 +23,10 @@ import com.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.courseFormat.Lesson; import com.jetbrains.edu.courseFormat.Task; import com.jetbrains.edu.courseFormat.TaskFile; -import com.jetbrains.edu.learning.CourseInfo; -import com.jetbrains.edu.learning.StudyLanguageManager; -import com.jetbrains.edu.learning.StudyTaskManager; -import com.jetbrains.edu.learning.StudyUtils; +import com.jetbrains.edu.learning.*; import com.jetbrains.edu.learning.stepic.StudyStepicConnector; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.io.*; import java.util.ArrayList; import java.util.List; @@ -60,76 +51,59 @@ public class StudyProjectGenerator { public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir) { final Course course = StudyStepicConnector.getCourse(mySelectedCourseInfo); if (course == null) return; - flushCourse(course); - StudyGenerator.initCourse(course, false); - final File courseDirectory = new File(myCoursesDir, course.getName()); - StudyGenerator.createCourse(course, baseDir, courseDirectory, project); - course.setCourseDirectory(new File(myCoursesDir, mySelectedCourseInfo.getName()).getAbsolutePath()); - VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); StudyTaskManager.getInstance(project).setCourse(course); - ToolWindowManagerEx.getInstanceEx(project).addToolWindowManagerListener(new OpenFirstTaskListener(project, course)); - } - - private static class OpenFirstTaskListener extends ToolWindowManagerAdapter { - private final Project myProject; - private final Course myCourse; - private boolean myInitialized = false; - - OpenFirstTaskListener(@NotNull final Project project, @NotNull final Course course) { - myProject = project; - myCourse = course; - } - - public void stateChanged() { - final AbstractProjectViewPane projectViewPane = ProjectView.getInstance(myProject).getCurrentProjectViewPane(); - if (projectViewPane == null || myInitialized) return; - JTree tree = projectViewPane.getTree(); - if (tree == null) { - return; - } - tree.updateUI(); - - ApplicationManager.getApplication().invokeLater(new Runnable() { + flushCourse(course); + ApplicationManager.getApplication().invokeLater( + new Runnable() { @Override public void run() { - LocalFileSystem.getInstance().refresh(false); - final Lesson firstLesson = StudyUtils.getFirst(myCourse.getLessons()); - final Task firstTask = StudyUtils.getFirst(firstLesson.getTaskList()); - final VirtualFile taskDir = firstTask.getTaskDir(myProject); - if (taskDir == null) return; - final Map taskFiles = firstTask.getTaskFiles(); - VirtualFile activeVirtualFile = null; - for (Map.Entry entry : taskFiles.entrySet()) { - final String name = entry.getKey(); - final TaskFile taskFile = entry.getValue(); - final VirtualFile virtualFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(name); - if (virtualFile != null) { - FileEditorManager.getInstance(myProject).openFile(virtualFile, true); - if (!taskFile.getAnswerPlaceholders().isEmpty()) { - activeVirtualFile = virtualFile; - } + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + StudyGenerator.initCourse(course, false); + final File courseDirectory = new File(myCoursesDir, course.getName()); + StudyGenerator.createCourse(course, baseDir, courseDirectory, project); + course.setCourseDirectory(new File(myCoursesDir, mySelectedCourseInfo.getName()).getAbsolutePath()); + VirtualFileManager.getInstance().refreshWithoutFileWatcher(true); + StudyProjectComponent.getInstance(project).registerStudyToolwindow(course); + openFirstTask(course, project); + } - } - if (activeVirtualFile != null) { - final PsiFile file = PsiManager.getInstance(myProject).findFile(activeVirtualFile); - ProjectView.getInstance(myProject).select(file, activeVirtualFile, true); - } else { - String first = StudyUtils.getFirst(taskFiles.keySet()); - if (first != null) { - NewVirtualFile firstFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(first); - if (firstFile != null) { - FileEditorManager.getInstance(myProject).openFile(firstFile, true); - } - } - } - myInitialized = true; - } - }, ModalityState.current(), new Condition() { - @Override - public boolean value(Object o) { - return myProject.isDisposed(); + }); } }); + } + + private static void openFirstTask(@NotNull final Course course, @NotNull final Project project) { + LocalFileSystem.getInstance().refresh(false); + final Lesson firstLesson = StudyUtils.getFirst(course.getLessons()); + final Task firstTask = StudyUtils.getFirst(firstLesson.getTaskList()); + final VirtualFile taskDir = firstTask.getTaskDir(project); + if (taskDir == null) return; + final Map taskFiles = firstTask.getTaskFiles(); + VirtualFile activeVirtualFile = null; + for (Map.Entry entry : taskFiles.entrySet()) { + final String name = entry.getKey(); + final TaskFile taskFile = entry.getValue(); + final VirtualFile virtualFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(name); + if (virtualFile != null) { + FileEditorManager.getInstance(project).openFile(virtualFile, true); + if (!taskFile.getAnswerPlaceholders().isEmpty()) { + activeVirtualFile = virtualFile; + } + } + } + if (activeVirtualFile != null) { + final PsiFile file = PsiManager.getInstance(project).findFile(activeVirtualFile); + ProjectView.getInstance(project).select(file, activeVirtualFile, true); + } else { + String first = StudyUtils.getFirst(taskFiles.keySet()); + if (first != null) { + NewVirtualFile firstFile = ((VirtualDirectoryImpl)taskDir).refreshAndFindChild(first); + if (firstFile != null) { + FileEditorManager.getInstance(project).openFile(firstFile, true); + } + } } } 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 35bf321f6331..30a40c6fc156 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 @@ -20,13 +20,14 @@ import java.util.List; public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware { public static final String STUDY_TOOL_WINDOW = "Course Description"; - private JPanel myContentPanel = new JPanel(); + @Override public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) { + JPanel contentPanel = new JPanel(); if (StudyTaskManager.getInstance(project).getCourse() != null) { - myContentPanel.setLayout(new BoxLayout(myContentPanel, BoxLayout.PAGE_AXIS)); - myContentPanel.add(Box.createRigidArea(new Dimension(10, 0))); + contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)); + contentPanel.add(Box.createRigidArea(new Dimension(10, 0))); StudyTaskManager taskManager = StudyTaskManager.getInstance(project); Course course = taskManager.getCourse(); if (course == null) { @@ -36,11 +37,11 @@ public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware { String description = UIUtil.toHtml(course.getDescription(), 5); String author = taskManager.getCourse().getAuthor(); String authorLabel = UIUtil.toHtml("Author: " + author, 5); - myContentPanel.add(new JLabel(courseName)); - myContentPanel.add(new JLabel(authorLabel)); - myContentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - myContentPanel.add(new JLabel(description)); - myContentPanel.add(Box.createRigidArea(new Dimension(0, 10))); + 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; @@ -56,25 +57,25 @@ public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware { 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); - myContentPanel.add(Box.createVerticalStrut(10)); - addStatistics(completedLessons); - addStatistics(completedTasks); + contentPanel.add(Box.createVerticalStrut(10)); + addStatistics(completedLessons, contentPanel); + addStatistics(completedTasks, contentPanel); double percent = (taskSolved * 100.0) / taskNum; - myContentPanel.add(Box.createRigidArea(new Dimension(0, 10))); + contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); StudyProgressBar studyProgressBar = new StudyProgressBar(percent / 100, 40, 10); - myContentPanel.add(studyProgressBar); - addStatistics(tasksLeft); + contentPanel.add(studyProgressBar); + addStatistics(tasksLeft, contentPanel); ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); - Content content = contentFactory.createContent(myContentPanel, "", true); + Content content = contentFactory.createContent(contentPanel, "", true); toolWindow.getContentManager().addContent(content); } } - private void addStatistics(String statistics) { + private static void addStatistics(String statistics, JPanel contentPanel) { String labelText = UIUtil.toHtml(statistics, 5); - myContentPanel.add(Box.createRigidArea(new Dimension(0, 10))); + contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); JLabel statisticLabel = new JLabel(labelText); - myContentPanel.add(statisticLabel); + contentPanel.add(statisticLabel); } }