blob: 72660fc9c2c6db782dddb77121e53cce13c25d03 [file] [log] [blame]
package com.jetbrains.python.edu.actions;
import com.intellij.icons.AllIcons;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.TabsListener;
import com.intellij.ui.tabs.impl.JBEditorTabs;
import com.intellij.util.PlatformIcons;
import com.jetbrains.python.edu.StudyTaskManager;
import com.jetbrains.python.edu.StudyUtils;
import com.jetbrains.python.edu.course.Task;
import com.jetbrains.python.edu.course.TaskFile;
import com.jetbrains.python.edu.course.UserTest;
import com.jetbrains.python.edu.editor.StudyEditor;
import com.jetbrains.python.edu.ui.StudyTestContentPanel;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class StudyEditInputAction extends DumbAwareAction {
public static final String TEST_TAB_NAME = "test";
public static final String USER_TEST_INPUT = "input";
public static final String USER_TEST_OUTPUT = "output";
private static final Logger LOG = Logger.getInstance(StudyEditInputAction.class.getName());
private JBEditorTabs tabbedPane;
private Map<TabInfo, UserTest> myEditableTabs = new HashMap<TabInfo, UserTest>();
public void showInput(final Project project) {
final Editor selectedEditor = StudyEditor.getSelectedEditor(project);
if (selectedEditor != null) {
FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
final VirtualFile openedFile = fileDocumentManager.getFile(selectedEditor.getDocument());
StudyTaskManager studyTaskManager = StudyTaskManager.getInstance(project);
assert openedFile != null;
TaskFile taskFile = studyTaskManager.getTaskFile(openedFile);
assert taskFile != null;
final Task currentTask = taskFile.getTask();
tabbedPane = new JBEditorTabs(project, ActionManager.getInstance(), IdeFocusManager.findInstance(), project);
tabbedPane.addListener(new TabsListener.Adapter() {
@Override
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
if (newSelection.getIcon() != null) {
int tabCount = tabbedPane.getTabCount();
VirtualFile taskDir = openedFile.getParent();
VirtualFile testsDir = taskDir.findChild(Task.USER_TESTS);
assert testsDir != null;
UserTest userTest = createUserTest(testsDir, currentTask);
userTest.setEditable(true);
StudyTestContentPanel testContentPanel = new StudyTestContentPanel(userTest);
TabInfo testTab = addTestTab(tabbedPane.getTabCount(), testContentPanel, currentTask, true);
myEditableTabs.put(testTab, userTest);
tabbedPane.addTabSilently(testTab, tabCount - 1);
tabbedPane.select(testTab, true);
}
}
});
List<UserTest> userTests = currentTask.getUserTests();
int i = 1;
for (UserTest userTest : userTests) {
String inputFileText = StudyUtils.getFileText(null, userTest.getInput(), false);
String outputFileText = StudyUtils.getFileText(null, userTest.getOutput(), false);
StudyTestContentPanel myContentPanel = new StudyTestContentPanel(userTest);
myContentPanel.addInputContent(inputFileText);
myContentPanel.addOutputContent(outputFileText);
TabInfo testTab = addTestTab(i, myContentPanel, currentTask, userTest.isEditable());
tabbedPane.addTabSilently(testTab, i - 1);
if (userTest.isEditable()) {
myEditableTabs.put(testTab, userTest);
}
i++;
}
TabInfo plusTab = new TabInfo(new JPanel());
plusTab.setIcon(PlatformIcons.ADD_ICON);
tabbedPane.addTabSilently(plusTab, tabbedPane.getTabCount());
final JBPopup hint =
JBPopupFactory.getInstance().createComponentPopupBuilder(tabbedPane.getComponent(), tabbedPane.getComponent())
.setResizable(true)
.setMovable(true)
.setRequestFocus(true)
.createPopup();
StudyEditor selectedStudyEditor = StudyEditor.getSelectedStudyEditor(project);
assert selectedStudyEditor != null;
hint.showInCenterOf(selectedStudyEditor.getComponent());
hint.addListener(new HintClosedListener(currentTask));
}
}
private static void flushBuffer(@NotNull final StringBuilder buffer, @NotNull final File file) {
PrintWriter printWriter = null;
try {
printWriter = new PrintWriter(new FileOutputStream(file));
printWriter.print(buffer.toString());
}
catch (FileNotFoundException e) {
LOG.error(e);
}
finally {
StudyUtils.closeSilently(printWriter);
}
StudyUtils.synchronize();
}
private static UserTest createUserTest(@NotNull final VirtualFile testsDir, @NotNull final Task currentTask) {
UserTest userTest = new UserTest();
List<UserTest> userTests = currentTask.getUserTests();
int testNum = userTests.size() + 1;
String inputName = USER_TEST_INPUT + testNum;
File inputFile = new File(testsDir.getPath(), inputName);
String outputName = USER_TEST_OUTPUT + testNum;
File outputFile = new File(testsDir.getPath(), outputName);
userTest.setInput(inputFile.getPath());
userTest.setOutput(outputFile.getPath());
userTests.add(userTest);
return userTest;
}
private TabInfo addTestTab(int nameIndex, final StudyTestContentPanel contentPanel, @NotNull final Task currentTask, boolean toBeClosable) {
TabInfo testTab = toBeClosable ? createClosableTab(contentPanel, currentTask) : new TabInfo(contentPanel);
return testTab.setText(TEST_TAB_NAME + String.valueOf(nameIndex));
}
private TabInfo createClosableTab(StudyTestContentPanel contentPanel, Task currentTask) {
TabInfo closableTab = new TabInfo(contentPanel);
final DefaultActionGroup tabActions = new DefaultActionGroup();
tabActions.add(new CloseTab(closableTab, currentTask));
closableTab.setTabLabelActions(tabActions, ActionPlaces.EDITOR_TAB);
return closableTab;
}
public void actionPerformed(AnActionEvent e) {
showInput(e.getProject());
}
private class HintClosedListener extends JBPopupAdapter {
private final Task myTask;
private HintClosedListener(@NotNull final Task task) {
myTask = task;
}
@Override
public void onClosed(LightweightWindowEvent event) {
for (final UserTest userTest : myTask.getUserTests()) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
if (userTest.isEditable()) {
File inputFile = new File(userTest.getInput());
File outputFile = new File(userTest.getOutput());
flushBuffer(userTest.getInputBuffer(), inputFile);
flushBuffer(userTest.getOutputBuffer(), outputFile);
}
}
});
}
}
}
private class CloseTab extends AnAction implements DumbAware {
private final TabInfo myTabInfo;
private final Task myTask;
public CloseTab(final TabInfo info, @NotNull final Task task) {
myTabInfo = info;
myTask = task;
}
@Override
public void update(final AnActionEvent e) {
e.getPresentation().setIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNew : AllIcons.Actions.Close);
e.getPresentation().setHoveredIcon(tabbedPane.isEditorTabs() ? AllIcons.Actions.CloseNewHovered : AllIcons.Actions.CloseHovered);
e.getPresentation().setVisible(UISettings.getInstance().SHOW_CLOSE_BUTTON);
e.getPresentation().setText("Delete test");
}
@Override
public void actionPerformed(final AnActionEvent e) {
tabbedPane.removeTab(myTabInfo);
UserTest userTest = myEditableTabs.get(myTabInfo);
File testInputFile = new File(userTest.getInput());
File testOutputFile = new File(userTest.getOutput());
if (testInputFile.delete() && testOutputFile.delete()) {
StudyUtils.synchronize();
} else {
LOG.error("failed to delete user tests");
}
myTask.getUserTests().remove(userTest);
}
}
}