EDU-207 IAE fixed
authorLiana Bakradze <liana.bakradze@jetbrains.com>
Wed, 1 Oct 2014 14:45:12 +0000 (18:45 +0400)
committerLiana Bakradze <liana.bakradze@jetbrains.com>
Wed, 1 Oct 2014 14:45:12 +0000 (18:45 +0400)
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCDocumentListener.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/CCEditorFactoryListener.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCAddTaskWindow.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/actions/CCDeleteTaskWindow.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskFile.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/format/TaskWindow.java
python/edu/course-creator/src/org/jetbrains/plugins/coursecreator/highlighting/CCTaskLineMarkerProvider.java

index 93722ab487b232f3e27091d8c23d8b937b86c43e..7e2559bcd1eb428a0a61f8cb3ac6d0992bd89f8d 100644 (file)
@@ -43,21 +43,21 @@ public abstract class CCDocumentListener extends DocumentAdapter {
   @Override
   public void documentChanged(DocumentEvent e) {
     if (e instanceof DocumentEventImpl) {
-      DocumentEventImpl event = (DocumentEventImpl)e;
-      Document document = e.getDocument();
-      int offset = e.getOffset();
-      int change = event.getNewLength() - event.getOldLength();
-      if (myTaskWindow != null) {
-        updateTaskWindowLength(e.getNewFragment(), myTaskWindow, change);
+        DocumentEventImpl event = (DocumentEventImpl)e;
+        Document document = e.getDocument();
+        int offset = e.getOffset();
+        int change = event.getNewLength() - event.getOldLength();
+        if (myTaskWindow != null) {
+          updateTaskWindowLength(e.getNewFragment(), myTaskWindow, change);
+        }
+        int newEnd = offset + event.getNewLength();
+        int newLine = document.getLineNumber(newEnd);
+        int lineChange = newLine - myOldLine;
+        myTaskFile.incrementLines(myOldLine + 1, lineChange);
+        int newEndOffsetInLine = offset + e.getNewLength() - document.getLineStartOffset(newLine);
+        int oldEndOffsetInLine = offset + e.getOldLength() - myOldLineStartOffset;
+        myTaskFile.updateLine(lineChange, myOldLine, newEndOffsetInLine, oldEndOffsetInLine);
       }
-      int newEnd = offset + event.getNewLength();
-      int newLine = document.getLineNumber(newEnd);
-      int lineChange = newLine - myOldLine;
-      myTaskFile.incrementLines(myOldLine + 1, lineChange);
-      int newEndOffsetInLine = offset + e.getNewLength() - document.getLineStartOffset(newLine);
-      int oldEndOffsetInLine = offset + e.getOldLength() - myOldLineStartOffset;
-      myTaskFile.updateLine(lineChange, myOldLine, newEndOffsetInLine, oldEndOffsetInLine);
-    }
   }
 
   protected abstract void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change);
index cac7aef44487f6dddfe8372117dc99f9cb006722..2952497483cfda9a65121b254ccc7be3e5af053a 100644 (file)
@@ -1,7 +1,12 @@
 package org.jetbrains.plugins.coursecreator;
 
+import com.intellij.codeInsight.hint.HintManager;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
+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.fileEditor.FileDocumentManager;
@@ -41,7 +46,11 @@ public class CCEditorFactoryListener implements EditorFactoryListener {
     TaskFileModificationListener listener = new TaskFileModificationListener(taskFile);
     CCProjectService.addDocumentListener(editor.getDocument(), listener);
     editor.getDocument().addDocumentListener(listener);
+    EditorActionManager.getInstance()
+      .setReadonlyFragmentModificationHandler(editor.getDocument(), new TaskWindowDeleteHandler(editor));
     CCProjectService.drawTaskWindows(virtualFile, editor, course);
+    editor.getColorsScheme().setColor(EditorColors.READONLY_FRAGMENT_BACKGROUND_COLOR, null);
+    taskFile.createGuardedBlocks(editor);
   }
 
   @Override
@@ -67,9 +76,20 @@ public class CCEditorFactoryListener implements EditorFactoryListener {
     protected void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change) {
         int newLength = taskWindow.getReplacementLength() + change;
         taskWindow.setReplacementLength(newLength <= 0 ? 0 : newLength);
-        if (fragment.equals("\n")) {
-          taskWindow.setReplacementLength(taskWindow.getLength() + 1);
-        }
+    }
+  }
+
+  private static class TaskWindowDeleteHandler implements ReadonlyFragmentModificationHandler {
+
+    private final Editor myEditor;
+
+    public TaskWindowDeleteHandler(@NotNull final Editor editor) {
+      myEditor = editor;
+    }
+
+    @Override
+    public void handle(ReadOnlyFragmentModificationException e) {
+      HintManager.getInstance().showErrorHint(myEditor, "Delete task window before editing its borders");
     }
   }
 }
index 476b2481d7ab65648287ebcccc5fe2c945651b77..453bbf49dc7e5b442b1de03619c2b759d9fc9a5a 100644 (file)
@@ -61,6 +61,7 @@ public class CCAddTaskWindow extends DumbAwareAction {
     int index = taskFile.getTaskWindows().size() + 1;
     taskFile.addTaskWindow(taskWindow, index);
     taskWindow.drawHighlighter(editor, false);
+    taskWindow.createGuardedBlocks(editor);
     DaemonCodeAnalyzerImpl.getInstance(project).restart(file);
   }
 
index cfc8e6949b021eae7092b45164ecca8d3df5b793..dbbe4230b396c8f69ea1125974359421f68050fc 100644 (file)
@@ -28,7 +28,7 @@ public class CCDeleteTaskWindow extends DumbAwareAction {
   }
 
   @Override
-  public void actionPerformed(AnActionEvent e) {
+  public void actionPerformed(@NotNull AnActionEvent e) {
     final Project project = e.getData(PlatformDataKeys.PROJECT);
     if (project == null) return;
     final PsiFile file = CommonDataKeys.PSI_FILE.getData(e.getDataContext());
@@ -55,6 +55,7 @@ public class CCDeleteTaskWindow extends DumbAwareAction {
       taskWindows.remove(myTaskWindow);
       editor.getMarkupModel().removeAllHighlighters();
       CCProjectService.drawTaskWindows(file.getVirtualFile(), editor, course);
+      taskFile.createGuardedBlocks(editor);
       DaemonCodeAnalyzerImpl.getInstance(project).restart(file);
     }
   }
index b88e375bc2657f0b7df2b675143ad9580b24c1e7..19498b9f3d1e2638d8593f40fdf4e55fa1570a1f 100644 (file)
@@ -2,6 +2,7 @@ package org.jetbrains.plugins.coursecreator.format;
 
 import com.google.gson.annotations.Expose;
 import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -14,7 +15,8 @@ public class TaskFile {
   @Expose public List<TaskWindow> task_windows = new ArrayList<TaskWindow>();
   public int myIndex;
 
-  public TaskFile() {}
+  public TaskFile() {
+  }
 
   public void addTaskWindow(@NotNull final TaskWindow taskWindow, int index) {
     taskWindow.setIndex(index);
@@ -79,14 +81,14 @@ public class TaskFile {
    */
   public void updateLine(int lineChange, int line, int newEndOffsetInLine, int oldEndOffsetInLine) {
     for (TaskWindow w : task_windows) {
-      if ((w.getLine() == line) && (w.getStart() >= oldEndOffsetInLine)) {
+      if ((w.getLine() == line) && (w.getStart() > oldEndOffsetInLine)) {
         int distance = w.getStart() - oldEndOffsetInLine;
         boolean coveredByPrevTW = false;
         int prevIndex = w.getIndex() - 1;
         if (CCProjectService.indexIsValid(prevIndex, task_windows)) {
           TaskWindow prevTW = task_windows.get(prevIndex);
           if (prevTW.getLine() == line) {
-            int endOffset = prevTW.getStart() + prevTW.getLength();
+            int endOffset = prevTW.getStart() + prevTW.getReplacementLength();
             if (endOffset >= newEndOffsetInLine) {
               coveredByPrevTW = true;
             }
@@ -104,7 +106,7 @@ public class TaskFile {
     target.setIndex(myIndex);
     for (TaskWindow taskWindow : task_windows) {
       TaskWindow savedWindow = new TaskWindow(taskWindow.getLine(), taskWindow.getStart(),
-                                    taskWindow.getLength(), "");
+                                              taskWindow.getLength(), "");
       target.getTaskWindows().add(savedWindow);
       savedWindow.setIndex(taskWindow.getIndex());
     }
@@ -117,4 +119,13 @@ public class TaskFile {
       taskWindowUpdated.setStart(taskWindow.getStart());
     }
   }
+
+  /**
+   * Marks symbols adjacent to task windows as read-only fragments
+   */
+  public void createGuardedBlocks(@NotNull final Editor editor) {
+    for (TaskWindow taskWindow : task_windows) {
+      taskWindow.createGuardedBlocks(editor);
+    }
+  }
 }
index 6b1be7ef3e7d2d747e3fdba43a6ecf76e8c5259d..dc7551929e30a505a2e12a5ef2b868ab662327e8 100644 (file)
@@ -3,18 +3,22 @@ package org.jetbrains.plugins.coursecreator.format;
 import com.google.gson.annotations.Expose;
 import com.intellij.openapi.editor.Document;
 import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
 import com.intellij.openapi.editor.colors.EditorColors;
 import com.intellij.openapi.editor.colors.EditorColorsManager;
+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.editor.markup.TextAttributes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.JBColor;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.plugins.coursecreator.CCProjectService;
 
 import java.io.File;
+import java.util.List;
 
 public class TaskWindow implements Comparable{
 
@@ -74,11 +78,12 @@ public class TaskWindow implements Comparable{
     int endOffset = startOffset + highlighterLength;
     TextAttributes defaultTestAttributes =
       EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
+    defaultTestAttributes.setEffectColor(JBColor.BLUE);
     RangeHighlighter highlighter =
       editor.getMarkupModel().addRangeHighlighter(startOffset, endOffset, HighlighterLayer.LAST + 1, defaultTestAttributes,
                                                   HighlighterTargetArea.EXACT_RANGE);
     highlighter.setGreedyToLeft(true);
-    highlighter.setGreedyToRight(false);
+    highlighter.setGreedyToRight(true);
   }
 
   public int getIndex() {
@@ -127,4 +132,26 @@ public class TaskWindow implements Comparable{
   public int getLength() {
     return length;
   }
+
+  public void createGuardedBlocks(@NotNull final Editor editor) {
+    Document document = editor.getDocument();
+    if (document instanceof DocumentImpl) {
+      DocumentImpl documentImpl = (DocumentImpl)document;
+      List<RangeMarker> blocks = documentImpl.getGuardedBlocks();
+        int start = getRealStartOffset(document);
+        int end = start + getReplacementLength();
+        if (start != 0) {
+          createGuardedBlock(editor, blocks, start - 1, start);
+        }
+        if (end != document.getTextLength()) {
+          createGuardedBlock(editor, blocks, end, end + 1);
+        }
+      }
+  }
+
+  public 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);
+  }
 }
\ No newline at end of file
index e294b3f85a132ebf2b11c8e809fd6f4090cab0ca..c85c8e2a3ae83824f65d7ca12c3ce5f7ab09863b 100644 (file)
@@ -56,6 +56,7 @@ public class CCTaskLineMarkerProvider implements LineMarkerProvider {
           final int lineStartOffset = document.getLineStartOffset(taskWindow.line);
           final int offset = lineStartOffset + taskWindow.start;
           if (offset > document.getTextLength()) continue;
+          if (offset + taskWindow.getReplacementLength() > document.getTextLength()) continue;
           final TextRange textRange = TextRange.create(offset, offset + taskWindow.getReplacementLength());
           @SuppressWarnings("unchecked")
           final LineMarkerInfo info = new LineMarkerInfo(element, textRange,