extracted studyProjectComponent from studyTaskManager

This commit is contained in:
Ekaterina Tuzova
2015-02-13 21:55:04 +03:00
parent ee3a730fb5
commit 8551a1f82f
6 changed files with 399 additions and 404 deletions
@@ -22,8 +22,8 @@
<project-components>
<component>
<implementation-class>com.jetbrains.edu.learning.StudyTaskManager</implementation-class>
<interface-class>com.jetbrains.edu.learning.StudyTaskManager</interface-class>
<implementation-class>com.jetbrains.edu.learning.StudyProjectComponent</implementation-class>
<interface-class>com.jetbrains.edu.learning.StudyProjectComponent</interface-class>
</component>
</project-components>
@@ -72,5 +72,7 @@
serviceImplementation="com.jetbrains.edu.learning.StudyInstructionPainter" overrides="true"/>
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<highlightErrorFilter implementation="com.jetbrains.edu.learning.editor.StudyHighlightErrorFilter"/>
<projectService serviceInterface="com.jetbrains.edu.learning.StudyTaskManager"
serviceImplementation="com.jetbrains.edu.learning.StudyTaskManager"/>
</extensions>
</idea-plugin>
@@ -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<String, String> myDeletedShortcuts = new HashMap<String, String>();
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<String, String> 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<Lesson> lessons = course.getLessons();
if (StudyUtils.indexIsValid(lessonIndex, lessons)) {
final Lesson lesson = lessons.get(lessonIndex);
final List<Task> 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);
}
}
}
}
}
}
}
}
@@ -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<Element>, DumbAware {
private static final Logger LOG = Logger.getInstance(StudyTaskManager.class.getName());
public static final String COURSE_ELEMENT = "courseElement";
private static Map<String, String> myDeletedShortcuts = new HashMap<String, String>();
private final Project myProject;
private Course myCourse;
private FileCreatedByUserListener myListener;
public class StudyTaskManager implements PersistentStateComponent<StudyTaskManager>, 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<String, String> 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<Lesson> lessons = myCourse.getLessons();
if (StudyUtils.indexIsValid(lessonIndex, lessons)) {
final Lesson lesson = lessons.get(lessonIndex);
final List<Task> 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);
}
}
}
}
}
}
}
}
@@ -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<Lesson> 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);
}
}
});
}
});
}
/**
@@ -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<String, TaskFile> taskFiles = firstTask.getTaskFiles();
VirtualFile activeVirtualFile = null;
for (Map.Entry<String, TaskFile> 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<String, TaskFile> taskFiles = firstTask.getTaskFiles();
VirtualFile activeVirtualFile = null;
for (Map.Entry<String, TaskFile> 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);
}
}
}
}
@@ -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("<b>Author: </b>" + 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);
}
}