replaced notification about task file invalidation with task windows delete forbiddance
authorLiana Bakradze <liana.bakradze@jetbrains.com>
Tue, 30 Sep 2014 14:51:00 +0000 (18:51 +0400)
committerLiana Bakradze <liana.bakradze@jetbrains.com>
Tue, 30 Sep 2014 14:51:00 +0000 (18:51 +0400)
python/edu/learn-python/resources/META-INF/plugin.xml
python/edu/learn-python/src/com/jetbrains/python/edu/InvalidTaskFileFix.java [deleted file]
python/edu/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java
python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorFactoryListener.java
python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorNotificationProvider.java [deleted file]
python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyCheckAction.java
python/edu/learn-python/src/com/jetbrains/python/edu/actions/StudyRefreshTaskFileAction.java
python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java
python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskWindow.java
python/edu/learn-python/src/com/jetbrains/python/edu/editor/StudyEditor.java

index fdddec795a6536a89281e2450fdd3fb3ffb95d83..264dfba2049b15ad39b4cb0e2bb7f996b797b5b5 100644 (file)
@@ -76,7 +76,6 @@
     <applicationService serviceInterface="com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter"
         serviceImplementation="com.jetbrains.python.edu.StudyInstructionPainter" overrides="true"/>
     <errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
-    <editorNotificationProvider implementation="com.jetbrains.python.edu.StudyEditorNotificationProvider"/>
   </extensions>
   <extensions defaultExtensionNs="Pythonid">
     <visitorFilter language="Python" implementationClass="com.jetbrains.python.edu.highlighting.StudyVisitorFilter"/>
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/InvalidTaskFileFix.java b/python/edu/learn-python/src/com/jetbrains/python/edu/InvalidTaskFileFix.java
deleted file mode 100644 (file)
index b4e2ac5..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.jetbrains.python.edu;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-
-public class InvalidTaskFileFix {
-  private final Project myProject;
-  private CharSequence myText;
-  private int myOffset;
-
-  public InvalidTaskFileFix(@NotNull CharSequence text, int offset, @NotNull final Project project) {
-    myText = text;
-    myOffset = offset;
-    myProject = project;
-  }
-
-  public void applyFix(@NotNull final Document document) {
-    CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
-      @Override
-      public void run() {
-        ApplicationManager.getApplication().runWriteAction(new Runnable() {
-          @Override
-          public void run() {
-            //we replace only empty text in this fix
-            document.replaceString(myOffset, myOffset, myText);
-            FileDocumentManager.getInstance().saveDocument(document);
-          }
-        });
-      }
-    });
-  }
-
-  public Project getProject() {
-    return myProject;
-  }
-}
index a12e38738f727569829bd286d1b86c0a568b6e6b..8955032aa4085ae0120b3321b52605797d33f266 100644 (file)
@@ -2,19 +2,12 @@ package com.jetbrains.python.edu;
 
 
 import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
 import com.intellij.openapi.editor.event.DocumentAdapter;
 import com.intellij.openapi.editor.event.DocumentEvent;
 import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.ui.EditorNotifications;
 import com.jetbrains.python.edu.course.TaskFile;
 import com.jetbrains.python.edu.course.TaskWindow;
-import com.jetbrains.python.edu.editor.StudyEditor;
 
 /**
  * Listens changes in study files and updates
@@ -22,15 +15,12 @@ import com.jetbrains.python.edu.editor.StudyEditor;
  */
 public class StudyDocumentListener extends DocumentAdapter {
   private final TaskFile myTaskFile;
-  private final Project myProject;
   private int myOldLine;
   private int myOldLineStartOffset;
   private TaskWindow myTaskWindow;
-  private boolean myAffectTaskWindows = false;
 
-  public StudyDocumentListener(TaskFile taskFile, Project project) {
+  public StudyDocumentListener(TaskFile taskFile) {
     myTaskFile = taskFile;
-    myProject = project;
   }
 
 
@@ -38,40 +28,6 @@ public class StudyDocumentListener extends DocumentAdapter {
   // with fragments containing "\n"
   @Override
   public void beforeDocumentChange(DocumentEvent e) {
-    if (!myTaskFile.isValid()) {
-      return;
-    }
-    if (e instanceof DocumentEventImpl) {
-      DocumentEventImpl event = (DocumentEventImpl)e;
-      final Document document = event.getDocument();
-      if (event.getNewFragment().equals("")) {
-        int start = event.getOffset();
-        int end = start + event.getOldLength();
-        for (TaskWindow tw : myTaskFile.getTaskWindows()) {
-          int twStart = tw.getRealStartOffset(document);
-          int twEnd = twStart + tw.getLength();
-          if (isAffected(twStart, twEnd, start, end)) {
-            PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
-            if (psiFile == null) {
-              continue;
-            }
-            VirtualFile virtualFile = psiFile.getVirtualFile();
-            if (virtualFile == null) {
-              continue;
-            }
-            myAffectTaskWindows = true;
-            myTaskFile.setValidAndUpdate(false, virtualFile, myProject);
-            Editor editor = StudyEditor.getSelectedEditor(myProject);
-            if (editor == null) {
-              return;
-            }
-            editor.getMarkupModel().removeAllHighlighters();
-            StudyEditor.addFix(myTaskFile, new InvalidTaskFileFix(event.getOldFragment(), event.getOffset(), myProject));
-            return;
-          }
-        }
-      }
-    }
     int offset = e.getOffset();
     int oldEnd = offset + e.getOldLength();
     Document document = e.getDocument();
@@ -83,31 +39,11 @@ public class StudyDocumentListener extends DocumentAdapter {
     myTaskWindow = myTaskFile.getTaskWindow(document, pos);
   }
 
-  private static boolean isAffected(int taskWindowStart, int taskWindowEnd, int start, int end) {
-    boolean isCovered = taskWindowStart > start && taskWindowEnd < end;
-    boolean isIntersectLeft = taskWindowStart > start && taskWindowStart < end && taskWindowEnd >= end;
-    boolean isIntersectRight = taskWindowStart <= start && taskWindowEnd > start && taskWindowEnd < end;
-    return isCovered || isIntersectLeft || isIntersectRight;
-  }
-
   @Override
   public void documentChanged(DocumentEvent e) {
-    if (!myTaskFile.isTrackChanges()) {
-      return;
-    }
-    if (!myTaskFile.isValid() && !myAffectTaskWindows) {
-      StudyEditor.deleteFix(myTaskFile);
-      EditorNotifications.getInstance(myProject).updateAllNotifications();
-      return;
-    }
     if (e instanceof DocumentEventImpl) {
       DocumentEventImpl event = (DocumentEventImpl)e;
       Document document = e.getDocument();
-      if (myAffectTaskWindows) {
-        document.createGuardedBlock(0, document.getTextLength());
-        myAffectTaskWindows = false;
-        return;
-      }
       int offset = e.getOffset();
       int change = event.getNewLength() - event.getOldLength();
       if (myTaskWindow != null) {
index ebb4a0b09b7c50651695e3c91d919964d4bddf30..d88b64ad6899cdfcb87f36e8512ad2533468f7c9 100644 (file)
@@ -2,9 +2,13 @@ package com.jetbrains.python.edu;
 
 
 import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.*;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.ReadOnlyFragmentModificationException;
 import com.intellij.openapi.editor.actionSystem.EditorActionManager;
 import com.intellij.openapi.editor.actionSystem.ReadonlyFragmentModificationHandler;
+import com.intellij.openapi.editor.colors.EditorColors;
 import com.intellij.openapi.editor.event.EditorFactoryEvent;
 import com.intellij.openapi.editor.event.EditorFactoryListener;
 import com.intellij.openapi.editor.event.EditorMouseAdapter;
@@ -13,7 +17,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.EditorNotifications;
 import com.jetbrains.python.edu.course.StudyStatus;
 import com.jetbrains.python.edu.course.TaskFile;
 import com.jetbrains.python.edu.course.TaskWindow;
@@ -37,9 +40,6 @@ class StudyEditorFactoryListener implements EditorFactoryListener {
 
     @Override
     public void mouseClicked(EditorMouseEvent e) {
-      if (!myTaskFile.isValid()) {
-        return;
-      }
       Editor editor = e.getEditor();
       Point point = e.getMouseEvent().getPoint();
       LogicalPosition pos = editor.xyToLogicalPosition(point);
@@ -75,18 +75,16 @@ class StudyEditorFactoryListener implements EditorFactoryListener {
                 StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
                 TaskFile taskFile = taskManager.getTaskFile(openedFile);
                 if (taskFile != null) {
-                  EditorActionManager.getInstance().setReadonlyFragmentModificationHandler(document, new InvalidTaskFileModificationHandler());
+                  EditorActionManager.getInstance()
+                    .setReadonlyFragmentModificationHandler(document, new InvalidTaskFileModificationHandler());
                   taskFile.navigateToFirstTaskWindow(editor);
                   editor.addEditorMouseListener(new WindowSelectionListener(taskFile));
-                  StudyDocumentListener listener = new StudyDocumentListener(taskFile, project);
+                  StudyDocumentListener listener = new StudyDocumentListener(taskFile);
                   StudyEditor.addDocumentListener(document, listener);
                   document.addDocumentListener(listener);
                   taskFile.drawAllWindows(editor);
-                  if (!taskFile.isValid()) {
-                    document.createGuardedBlock(0, document.getTextLength());
-                    EditorNotifications.getInstance(project).updateNotifications(openedFile);
-                    editor.getMarkupModel().removeAllHighlighters();
-                  }
+                  taskFile.createGuardedBlocks(document, editor);
+                  editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
                 }
               }
             }
@@ -113,7 +111,7 @@ class StudyEditorFactoryListener implements EditorFactoryListener {
 
     @Override
     public void handle(ReadOnlyFragmentModificationException e) {
-      Messages.showErrorDialog("It's not allowed to modify invalid task files", "Invalid Task File Modification");
+      Messages.showErrorDialog("It's not allowed to delete task windows", "Invalid Task File Modification");
     }
   }
 }
diff --git a/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorNotificationProvider.java b/python/edu/learn-python/src/com/jetbrains/python/edu/StudyEditorNotificationProvider.java
deleted file mode 100644 (file)
index 756038d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.jetbrains.python.edu;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditor;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.EditorNotificationPanel;
-import com.intellij.ui.EditorNotifications;
-import com.jetbrains.python.edu.course.TaskFile;
-import com.jetbrains.python.edu.editor.StudyEditor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Class provides editor notifications about task file invalidation
- */
-public class StudyEditorNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
-  private static final Key<EditorNotificationPanel> KEY = Key.create("taskfile.invalid..editing.notification.panel");
-  private final Project myProject;
-
-  public StudyEditorNotificationProvider(@NotNull final Project project) {
-    myProject = project;
-  }
-
-  @NotNull
-  @Override
-  public Key<EditorNotificationPanel> getKey() {
-    return KEY;
-  }
-
-  @Nullable
-  @Override
-  public EditorNotificationPanel createNotificationPanel(@NotNull final VirtualFile file, @NotNull final FileEditor fileEditor) {
-    final TaskFile taskFile = StudyTaskManager.getInstance(myProject).getTaskFile(file);
-    if (taskFile == null) {
-      return null;
-    }
-    if (taskFile.isValid()) {
-      return null;
-    }
-    if (!(fileEditor instanceof StudyEditor)) {
-      return null;
-    }
-    final Editor editor = ((StudyEditor)fileEditor).getEditor();
-    EditorNotificationPanel panel = new EditorNotificationPanel();
-    panel.setText("Task file is invalid\n");
-    final InvalidTaskFileFix fix = StudyEditor.getFix(taskFile);
-    if (fix != null) {
-      panel.createActionLabel("fix file", new Runnable() {
-        @Override
-        public void run() {
-          final Document document = editor.getDocument();
-          StudyEditor.deleteGuardedBlocks(document);
-          editor.getMarkupModel().removeAllHighlighters();
-          taskFile.setTrackChanges(false);
-          fix.applyFix(document);
-          taskFile.setTrackChanges(true);
-          taskFile.drawAllWindows(editor);
-          StudyEditor.deleteFix(taskFile);
-          taskFile.setValidAndUpdate(true, file, fix.getProject());
-        }
-      });
-    }
-    else {
-      panel.createActionLabel("refresh task file", "RefreshTaskAction");
-    }
-    return panel;
-  }
-}
index 5a5b29e97ac5e519e8c85dc359c6b6e1c45359b4..04fc72a150a11fd0e546ecc12dbeb18361c96078 100644 (file)
@@ -103,12 +103,6 @@ public class StudyCheckAction extends DumbAwareAction {
             Task task = studyState.getTask();
             StudyStatus oldStatus = task.getStatus();
             Map<String, TaskFile> taskFiles = task.getTaskFiles();
-            for (TaskFile taskFile : taskFiles.values()) {
-              if (!taskFile.isValid()) {
-                createTestResultPopUp("It's not possible to check invalid files", MessageType.WARNING.getPopupBackground(), project);
-                return;
-              }
-            }
             VirtualFile taskDir = studyState.getTaskDir();
             flushWindows(task, taskDir);
             StudyRunAction runAction = (StudyRunAction)ActionManager.getInstance().getAction(StudyRunAction.ACTION_ID);
@@ -210,7 +204,7 @@ public class StudyCheckAction extends DumbAwareAction {
     if (virtualFile == null) {
       return;
     }
-    VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile, project);
+    VirtualFile answerFile = getCopyWithAnswers(taskDir, virtualFile, taskFile, answerTaskFile);
     for (TaskWindow taskWindow : answerTaskFile.getTaskWindows()) {
       Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
       if (document == null) {
@@ -227,8 +221,7 @@ public class StudyCheckAction extends DumbAwareAction {
   private VirtualFile getCopyWithAnswers(@NotNull final VirtualFile taskDir,
                                          @NotNull final VirtualFile file,
                                          @NotNull final TaskFile source,
-                                         @NotNull final TaskFile target,
-                                         @NotNull final Project project) {
+                                         @NotNull final TaskFile target) {
     VirtualFile copy = null;
     try {
 
@@ -237,7 +230,7 @@ public class StudyCheckAction extends DumbAwareAction {
       final Document document = documentManager.getDocument(copy);
       if (document != null) {
         TaskFile.copy(source, target);
-        StudyDocumentListener listener = new StudyDocumentListener(target, project);
+        StudyDocumentListener listener = new StudyDocumentListener(target);
         document.addDocumentListener(listener);
         for (TaskWindow taskWindow : target.getTaskWindows()) {
           if (!taskWindow.isValid(document)) {
@@ -274,7 +267,7 @@ public class StudyCheckAction extends DumbAwareAction {
   }
 
   @Override
-  public void actionPerformed(AnActionEvent e) {
+  public void actionPerformed(@NotNull AnActionEvent e) {
     Project project = e.getProject();
     if (project != null) {
       check(project);
index 8d85802f238e8dabaf71125dcf1cd94182742c20..a379ccf18239240cd04cc01cdd232b1230b1962f 100644 (file)
@@ -56,11 +56,11 @@ public class StudyRefreshTaskFileAction extends DumbAwareAction {
     assert openedFile != null;
     final TaskFile selectedTaskFile = taskManager.getTaskFile(openedFile);
     assert selectedTaskFile != null;
-    selectedTaskFile.setValidAndUpdate(true, openedFile, project);
     String openedFileName = openedFile.getName();
     Task currentTask = selectedTaskFile.getTask();
     resetTaskFile(document, project, course, selectedTaskFile, openedFileName, currentTask);
     selectedTaskFile.drawAllWindows(editor);
+    selectedTaskFile.createGuardedBlocks(document, editor);
     ApplicationManager.getApplication().invokeLater(new Runnable() {
       @Override
       public void run() {
index e3628d1c0c4c018bc0e7803baa97bb8255a6c647..6f082967475d5962bb34a8369f361c72f4974efc 100644 (file)
@@ -3,10 +3,13 @@ package com.jetbrains.python.edu.course;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.impl.DocumentImpl;
+import com.intellij.openapi.editor.markup.HighlighterLayer;
+import com.intellij.openapi.editor.markup.HighlighterTargetArea;
+import com.intellij.openapi.editor.markup.RangeHighlighter;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.EditorNotifications;
 import com.intellij.util.xmlb.annotations.Transient;
 import com.jetbrains.python.edu.StudyUtils;
 import org.jetbrains.annotations.NotNull;
@@ -30,8 +33,6 @@ public class TaskFile implements Stateful {
   private TaskWindow mySelectedTaskWindow = null;
   public int myIndex = -1;
   private boolean myUserCreated = false;
-  private boolean myValid = true;
-  private boolean myTrackChanges = true;
 
   /**
    * @return if all the windows in task file are marked as resolved
@@ -97,9 +98,6 @@ public class TaskFile implements Stateful {
 
   public void drawAllWindows(Editor editor) {
     for (TaskWindow taskWindow : taskWindows) {
-      if (!taskWindow.isValid(editor.getDocument())) {
-        setValid(false);
-      }
       taskWindow.draw(editor, false, false);
     }
   }
@@ -264,24 +262,29 @@ public class TaskFile implements Stateful {
     return taskWindows.size() > 0 && getStatus() == StudyStatus.Failed;
   }
 
-  public boolean isValid() {
-    return myValid;
-  }
-
-  public void setValid(boolean isValid) {
-    myValid = isValid;
-  }
-
-  public void setValidAndUpdate(boolean isValid, VirtualFile file, Project project) {
-    myValid = isValid;
-    EditorNotifications.getInstance(project).updateNotifications(file);
-  }
-
-  public boolean isTrackChanges() {
-    return myTrackChanges;
+  /**
+   * Marks symbols adjacent to task windows as read-only fragments
+   */
+  public void createGuardedBlocks(@NotNull final Document document, @NotNull final Editor editor) {
+    if (document instanceof DocumentImpl) {
+      DocumentImpl documentImpl = (DocumentImpl)document;
+      List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
+      for (TaskWindow taskWindow : taskWindows) {
+        int start = taskWindow.getRealStartOffset(document);
+        int end = start + taskWindow.getLength();
+        if (start != 0) {
+          createGuardedBlock(editor, blocks, start - 1, start);
+        }
+        if (end != document.getTextLength()) {
+          createGuardedBlock(editor, blocks, end, end + 1);
+        }
+      }
+    }
   }
 
-  public void setTrackChanges(boolean trackChanges) {
-    myTrackChanges = trackChanges;
+  private static void createGuardedBlock(Editor editor, List<RangeMarker> blocks, int start, int end) {
+    RangeHighlighter rh = editor.getMarkupModel()
+      .addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE);
+    blocks.add(rh);
   }
 }
index 3e87f6c5e659f1521a0d1b754b8222e4c9e620f5..674ffcdecceae2b56894c53f6717c31beb491467 100644 (file)
@@ -203,7 +203,7 @@ public class TaskWindow implements Comparable, Stateful {
         File resourceFile = StudyUtils.copyResourceFile(virtualFile.getName(), windowCopy.getName(), project, usersTaskFile.getTask());
         TaskFile windowTaskFile = new TaskFile();
         TaskFile.copy(answerTaskFile, windowTaskFile);
-        StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile, project);
+        StudyDocumentListener listener = new StudyDocumentListener(windowTaskFile);
         windowDocument.addDocumentListener(listener);
         int start = getRealStartOffset(windowDocument);
         int end = start + getLength();
index 958eb45951b2f22d9faefbb3d18308de39d0bb66..1a06e7ade6ab398110901b11668668553138850b 100644 (file)
@@ -30,7 +30,6 @@ import com.intellij.ui.HideableTitledPanel;
 import com.intellij.ui.JBColor;
 import com.intellij.util.ui.EmptyClipboardOwner;
 import com.intellij.util.ui.UIUtil;
-import com.jetbrains.python.edu.InvalidTaskFileFix;
 import com.jetbrains.python.edu.StudyDocumentListener;
 import com.jetbrains.python.edu.StudyTaskManager;
 import com.jetbrains.python.edu.actions.*;
@@ -58,7 +57,6 @@ import java.util.List;
  */
 public class StudyEditor implements TextEditor {
   private static final String TASK_TEXT_HEADER = "Task Text";
-  private static Map<TaskFile, InvalidTaskFileFix> myFixes = new HashMap<TaskFile, InvalidTaskFileFix>();
   private final FileEditor myDefaultEditor;
   private final JComponent myComponent;
   private final TaskFile myTaskFile;
@@ -120,19 +118,6 @@ public class StudyEditor implements TextEditor {
     }
   }
 
-  public static void addFix(@NotNull final TaskFile file, @NotNull final InvalidTaskFileFix fix) {
-    myFixes.put(file, fix);
-  }
-
-  @Nullable
-  public static InvalidTaskFileFix getFix(TaskFile file) {
-    return myFixes.get(file);
-  }
-
-  public static void deleteFix(TaskFile file) {
-    myFixes.remove(file);
-  }
-
   class CopyListener extends MouseAdapter {
     final JTextPane myTextPane;