fixed encoding problems
[idea/community.git] / python / edu / learn-python / src / com / jetbrains / python / edu / actions / StudyEditInputAction.java
1 package com.jetbrains.python.edu.actions;
2
3 import com.intellij.icons.AllIcons;
4 import com.intellij.ide.ui.UISettings;
5 import com.intellij.openapi.actionSystem.*;
6 import com.intellij.openapi.application.ApplicationManager;
7 import com.intellij.openapi.diagnostic.Logger;
8 import com.intellij.openapi.editor.Editor;
9 import com.intellij.openapi.fileEditor.FileDocumentManager;
10 import com.intellij.openapi.project.DumbAware;
11 import com.intellij.openapi.project.DumbAwareAction;
12 import com.intellij.openapi.project.Project;
13 import com.intellij.openapi.ui.popup.JBPopup;
14 import com.intellij.openapi.ui.popup.JBPopupAdapter;
15 import com.intellij.openapi.ui.popup.JBPopupFactory;
16 import com.intellij.openapi.ui.popup.LightweightWindowEvent;
17 import com.intellij.openapi.vfs.VirtualFile;
18 import com.intellij.openapi.wm.IdeFocusManager;
19 import com.intellij.ui.tabs.TabInfo;
20 import com.intellij.ui.tabs.TabsListener;
21 import com.intellij.ui.tabs.impl.JBEditorTabs;
22 import com.intellij.util.PlatformIcons;
23 import com.jetbrains.python.edu.StudyTaskManager;
24 import com.jetbrains.python.edu.StudyUtils;
25 import com.jetbrains.python.edu.course.Task;
26 import com.jetbrains.python.edu.course.TaskFile;
27 import com.jetbrains.python.edu.course.UserTest;
28 import com.jetbrains.python.edu.editor.StudyEditor;
29 import com.jetbrains.python.edu.ui.StudyTestContentPanel;
30 import org.jetbrains.annotations.NotNull;
31
32 import javax.swing.*;
33 import java.io.File;
34 import java.io.FileNotFoundException;
35 import java.io.FileOutputStream;
36 import java.io.PrintWriter;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40
41 public class StudyEditInputAction extends DumbAwareAction {
42
43   public static final String TEST_TAB_NAME = "test";
44   public static final String USER_TEST_INPUT = "input";
45   public static final String USER_TEST_OUTPUT = "output";
46   private static final Logger LOG = Logger.getInstance(StudyEditInputAction.class.getName());
47   private JBEditorTabs tabbedPane;
48   private Map<TabInfo, UserTest> myEditableTabs = new HashMap<TabInfo, UserTest>();
49
50   public void showInput(final Project project) {
51     final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
52     if (selectedEditor != null) {
53       FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
54       final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
55       StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(project);
56       assert openedFile != null;
57       TaskFile taskFile = studyTaskManager.getTaskFile(openedFile);
58       assert taskFile != null;
59       final Task currentTask = taskFile.getTask();
60       tabbedPane = new JBEditorTabs(project, ActionManager.getInstance(), IdeFocusManager.findInstance(), project);
61       tabbedPane.addListener(new TabsListener.Adapter() {
62         @Override
63         public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
64           if (newSelection.getIcon() != null) {
65             int tabCount = tabbedPane.getTabCount();
66             VirtualFile taskDir = openedFile.getParent();
67             VirtualFile testsDir = taskDir.findChild(Task.USER_TESTS);
68             assert testsDir != null;
69             UserTest userTest = createUserTest(testsDir, currentTask);
70             userTest.setEditable(true);
71             StudyTestContentPanel testContentPanel = new StudyTestContentPanel(userTest);
72             TabInfo testTab = addTestTab(tabbedPane.getTabCount(), testContentPanel, currentTask, true);
73             myEditableTabs.put(testTab, userTest);
74             tabbedPane.addTabSilently(testTab, tabCount - 1);
75             tabbedPane.select(testTab, true);
76           }
77         }
78       });
79       List<UserTest> userTests = currentTask.getUserTests();
80       int i = 1;
81       for (UserTest userTest : userTests) {
82         String inputFileText = StudyUtils.getFileText(null, userTest.getInput(), false, "UTF-8");
83         String outputFileText = StudyUtils.getFileText(null, userTest.getOutput(), false, "UTF-8");
84         StudyTestContentPanel myContentPanel = new StudyTestContentPanel(userTest);
85         myContentPanel.addInputContent(inputFileText);
86         myContentPanel.addOutputContent(outputFileText);
87         TabInfo testTab = addTestTab(i, myContentPanel, currentTask, userTest.isEditable());
88         tabbedPane.addTabSilently(testTab, i - 1);
89         if (userTest.isEditable()) {
90           myEditableTabs.put(testTab, userTest);
91         }
92         i++;
93       }
94       TabInfo plusTab = new TabInfo(new JPanel());
95       plusTab.setIcon(PlatformIcons.ADD_ICON);
96       tabbedPane.addTabSilently(plusTab, tabbedPane.getTabCount());
97       final JBPopup hint =
98         JBPopupFactory.getInstance().createComponentPopupBuilder(tabbedPane.getComponent(), tabbedPane.getComponent())
99           .setResizable(true)
100           .setMovable(true)
101           .setRequestFocus(true)
102           .createPopup();
103       StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
104       assert selectedStudyEditor != null;
105       hint.showInCenterOf(selectedStudyEditor.getComponent());
106       hint.addListener(new HintClosedListener(currentTask));
107     }
108   }
109
110
111   private static void flushBuffer(@NotNull final StringBuilder buffer, @NotNull final File file) {
112     PrintWriter printWriter = null;
113     try {
114       printWriter = new PrintWriter(new FileOutputStream(file));
115       printWriter.print(buffer.toString());
116     }
117     catch (FileNotFoundException e) {
118       LOG.error(e);
119     }
120     finally {
121       StudyUtils.closeSilently(printWriter);
122     }
123     StudyUtils.synchronize();
124   }
125
126   private static UserTest createUserTest(@NotNull final VirtualFile testsDir, @NotNull final Task currentTask) {
127     UserTest userTest = new UserTest();
128     List<UserTest> userTests = currentTask.getUserTests();
129     int testNum = userTests.size() + 1;
130     String inputName = USER_TEST_INPUT + testNum;
131     File inputFile = new File(testsDir.getPath(), inputName);
132     String outputName = USER_TEST_OUTPUT + testNum;
133     File outputFile = new File(testsDir.getPath(), outputName);
134     userTest.setInput(inputFile.getPath());
135     userTest.setOutput(outputFile.getPath());
136     userTests.add(userTest);
137     return userTest;
138   }
139
140   private TabInfo addTestTab(int nameIndex, final StudyTestContentPanel contentPanel, @NotNull final Task currentTask, boolean toBeClosable) {
141     TabInfo testTab = toBeClosable ? createClosableTab(contentPanel, currentTask) : new TabInfo(contentPanel);
142     return testTab.setText(TEST_TAB_NAME + String.valueOf(nameIndex));
143   }
144
145   private TabInfo createClosableTab(StudyTestContentPanel contentPanel, Task currentTask) {
146     TabInfo closableTab = new TabInfo(contentPanel);
147     final DefaultActionGroup tabActions = new DefaultActionGroup();
148     tabActions.add(new CloseTab(closableTab, currentTask));
149     closableTab.setTabLabelActions(tabActions, ActionPlaces.EDITOR_TAB);
150     return closableTab;
151   }
152
153   public void actionPerformed(AnActionEvent e) {
154     showInput(e.getProject());
155   }
156
157   private class HintClosedListener extends  JBPopupAdapter {
158     private final Task myTask;
159     private HintClosedListener(@NotNull final Task task) {
160       myTask = task;
161     }
162
163     @Override
164     public void onClosed(LightweightWindowEvent event) {
165       for (final UserTest userTest : myTask.getUserTests()) {
166         ApplicationManager.getApplication().runWriteAction(new Runnable() {
167           @Override
168           public void run() {
169             if (userTest.isEditable()) {
170               File inputFile = new File(userTest.getInput());
171               File outputFile = new File(userTest.getOutput());
172               flushBuffer(userTest.getInputBuffer(), inputFile);
173               flushBuffer(userTest.getOutputBuffer(), outputFile);
174             }
175           }
176         });
177       }
178     }
179   }
180
181   private class CloseTab extends AnAction implements DumbAware {
182
183     private final TabInfo myTabInfo;
184     private final Task myTask;
185
186     public CloseTab(final TabInfo info, @NotNull final Task task) {
187       myTabInfo = info;
188       myTask = task;
189     }
190
191     @Override
192     public void update(final AnActionEvent e) {
193       e.getPresentation().setIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNew : AllIcons.Actions.Close);
194       e.getPresentation().setHoveredIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNewHovered : AllIcons.Actions.CloseHovered);
195       e.getPresentation().setVisible(UISettings.getInstance().SHOW_CLOSE_BUTTON);
196       e.getPresentation().setText("Delete test");
197     }
198
199     @Override
200     public void actionPerformed(final AnActionEvent e) {
201       tabbedPane.removeTab(myTabInfo);
202       UserTest userTest = myEditableTabs.get(myTabInfo);
203       File testInputFile = new File(userTest.getInput());
204       File testOutputFile = new File(userTest.getOutput());
205       if (testInputFile.delete() && testOutputFile.delete()) {
206         StudyUtils.synchronize();
207       } else {
208         LOG.error("failed to delete user tests");
209       }
210       myTask.getUserTests().remove(userTest);
211     }
212   }
213 }