4add8f4ce41431553809a227b7fbf532591cec4e
[idea/community.git] / python / edu / learn-python / src / com / jetbrains / python / edu / StudyUtils.java
1 package com.jetbrains.python.edu;
2
3 import com.intellij.ide.SaveAndSyncHandlerImpl;
4 import com.intellij.ide.projectView.actions.MarkRootActionBase;
5 import com.intellij.openapi.actionSystem.AnActionEvent;
6 import com.intellij.openapi.actionSystem.Presentation;
7 import com.intellij.openapi.application.ApplicationManager;
8 import com.intellij.openapi.diagnostic.Logger;
9 import com.intellij.openapi.editor.Document;
10 import com.intellij.openapi.fileEditor.FileDocumentManager;
11 import com.intellij.openapi.fileEditor.FileEditor;
12 import com.intellij.openapi.fileEditor.FileEditorManager;
13 import com.intellij.openapi.module.Module;
14 import com.intellij.openapi.module.ModuleManager;
15 import com.intellij.openapi.module.ModuleUtilCore;
16 import com.intellij.openapi.project.Project;
17 import com.intellij.openapi.projectRoots.Sdk;
18 import com.intellij.openapi.roots.ContentEntry;
19 import com.intellij.openapi.roots.ModifiableRootModel;
20 import com.intellij.openapi.roots.ModuleRootManager;
21 import com.intellij.openapi.util.TextRange;
22 import com.intellij.openapi.util.io.FileUtil;
23 import com.intellij.openapi.vfs.VirtualFile;
24 import com.intellij.openapi.vfs.VirtualFileManager;
25 import com.intellij.openapi.wm.ToolWindowManager;
26 import com.intellij.util.ui.UIUtil;
27 import com.jetbrains.python.edu.course.*;
28 import com.jetbrains.python.edu.editor.StudyEditor;
29 import com.jetbrains.python.edu.ui.StudyToolWindowFactory;
30 import com.jetbrains.python.sdk.PythonSdkType;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import java.io.*;
35 import java.util.Collection;
36
37 public class StudyUtils {
38   private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName());
39
40   public static void closeSilently(Closeable stream) {
41     if (stream != null) {
42       try {
43         stream.close();
44       }
45       catch (IOException e) {
46         // close silently
47       }
48     }
49   }
50
51   public static boolean isZip(String fileName) {
52     return fileName.contains(".zip");
53   }
54
55   public static <T> T getFirst(Iterable<T> container) {
56     return container.iterator().next();
57   }
58
59   public static boolean indexIsValid(int index, Collection collection) {
60     int size = collection.size();
61     return index >= 0 && index < size;
62   }
63
64   @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
65   @Nullable
66   public static String getFileText(String parentDir, String fileName, boolean wrapHTML) {
67
68     File inputFile = parentDir != null ? new File(parentDir, fileName) : new File(fileName);
69     if (!inputFile.exists()) return null;
70     StringBuilder taskText = new StringBuilder();
71     BufferedReader reader = null;
72     try {
73       reader = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile)));
74       String line;
75       while ((line = reader.readLine()) != null) {
76         taskText.append(line).append("\n");
77         if (wrapHTML) {
78           taskText.append("<br>");
79         }
80       }
81       return wrapHTML ? UIUtil.toHtml(taskText.toString()) : taskText.toString();
82     }
83     catch (IOException e) {
84       LOG.info("Failed to get file text from file " + fileName, e);
85     }
86     finally {
87       closeSilently(reader);
88     }
89     return null;
90   }
91
92   public static void updateAction(AnActionEvent e) {
93     Presentation presentation = e.getPresentation();
94     presentation.setEnabled(false);
95     presentation.setVisible(false);
96     Project project = e.getProject();
97     if (project != null) {
98       FileEditor[] editors = FileEditorManager.getInstance(project).getAllEditors();
99       for (FileEditor editor : editors) {
100         if (editor instanceof StudyEditor) {
101           presentation.setEnabled(true);
102           presentation.setVisible(true);
103         }
104       }
105     }
106   }
107
108   public static void updateStudyToolWindow(Project project) {
109     ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager()
110       .removeAllContents(false);
111     StudyToolWindowFactory factory = new StudyToolWindowFactory();
112     factory
113       .createToolWindowContent(project, ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW));
114   }
115
116   public static void synchronize() {
117     FileDocumentManager.getInstance().saveAllDocuments();
118     SaveAndSyncHandlerImpl.refreshOpenFiles();
119     VirtualFileManager.getInstance().refreshWithoutFileWatcher(true);
120   }
121
122   /**
123    * Gets number index in directory names like "task1", "lesson2"
124    *
125    * @param fullName    full name of directory
126    * @param logicalName part of name without index
127    * @return index of object
128    */
129   public static int getIndex(@NotNull final String fullName, @NotNull final String logicalName) {
130     if (!fullName.contains(logicalName)) {
131       throw new IllegalArgumentException();
132     }
133     return Integer.parseInt(fullName.substring(logicalName.length())) - 1;
134   }
135
136   @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
137   public static VirtualFile flushWindows(TaskFile taskFile, VirtualFile file) {
138     VirtualFile taskDir = file.getParent();
139     VirtualFile fileWindows = null;
140     final Document document = FileDocumentManager.getInstance().getDocument(file);
141     if (document == null) {
142       LOG.debug("Couldn't flush windows");
143       return null;
144     }
145     if (taskDir != null) {
146       String name = file.getNameWithoutExtension() + "_windows";
147       PrintWriter printWriter = null;
148       try {
149         fileWindows = taskDir.createChildData(taskFile, name);
150         printWriter = new PrintWriter(new FileOutputStream(fileWindows.getPath()));
151         for (TaskWindow taskWindow : taskFile.getTaskWindows()) {
152           if (!taskWindow.isValid(document)) {
153             printWriter.println("#educational_plugin_window = ");
154             continue;
155           }
156           int start = taskWindow.getRealStartOffset(document);
157           String windowDescription = document.getText(new TextRange(start, start + taskWindow.getLength()));
158           printWriter.println("#educational_plugin_window = " + windowDescription);
159         }
160         ApplicationManager.getApplication().runWriteAction(new Runnable() {
161           @Override
162           public void run() {
163             FileDocumentManager.getInstance().saveDocument(document);
164           }
165         });
166       }
167       catch (IOException e) {
168         LOG.error(e);
169       }
170       finally {
171         closeSilently(printWriter);
172         synchronize();
173       }
174     }
175     return fileWindows;
176   }
177
178   public static void deleteFile(VirtualFile file) {
179     try {
180       file.delete(StudyUtils.class);
181     }
182     catch (IOException e) {
183       LOG.error(e);
184     }
185   }
186
187   public static File copyResourceFile(String sourceName, String copyName, Project project, Task task)
188     throws IOException {
189     StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
190     Course course = taskManager.getCourse();
191     int taskNum = task.getIndex() + 1;
192     int lessonNum = task.getLesson().getIndex() + 1;
193     assert course != null;
194     String pathToResource =
195       FileUtil.join(new File(course.getResourcePath()).getParent(), Lesson.LESSON_DIR + lessonNum, Task.TASK_DIR + taskNum);
196     File resourceFile = new File(pathToResource, copyName);
197     FileUtil.copy(new File(pathToResource, sourceName), resourceFile);
198     return resourceFile;
199   }
200
201   @Nullable
202   public static Sdk findPythonSdk(@NotNull final Project project) {
203     return PythonSdkType.findPythonSdk(ModuleManager.getInstance(project).getModules()[0]);
204   }
205
206   public static void markDirAsSourceRoot(@NotNull final VirtualFile dir, @NotNull final Project project) {
207     final Module module = ModuleUtilCore.findModuleForFile(dir, project);
208     if (module == null) {
209       LOG.info("Module for " + dir.getPath() + " was not found");
210       return;
211     }
212     final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
213     ContentEntry entry = MarkRootActionBase.findContentEntry(model, dir);
214     if (entry == null) {
215       LOG.info("Content entry for " + dir.getPath() + " was not found");
216       return;
217     }
218     entry.addSourceFolder(dir, false);
219     ApplicationManager.getApplication().runWriteAction(new Runnable() {
220       @Override
221       public void run() {
222         model.commit();
223         module.getProject().save();
224       }
225     });
226   }
227 }