fixed EDU-233, switched to flat model in offset listener
authorliana.bakradze <liana.bakradze@jetbrains.com>
Sun, 26 Oct 2014 20:02:56 +0000 (23:02 +0300)
committerliana.bakradze <liana.bakradze@jetbrains.com>
Sun, 26 Oct 2014 20:02:56 +0000 (23:02 +0300)
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/CCCreateCourseArchive.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/learn-python/src/com/jetbrains/python/edu/StudyDocumentListener.java
python/edu/learn-python/src/com/jetbrains/python/edu/course/TaskFile.java

index 3573216e9efa8b1d8139fe0245afe046c252a08a..b1917292df32f67393b52de22b8e748541268d18 100644 (file)
@@ -1,24 +1,23 @@
 package org.jetbrains.plugins.coursecreator;
 
 import com.intellij.openapi.editor.Document;
-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 org.jetbrains.plugins.coursecreator.format.TaskFile;
 import org.jetbrains.plugins.coursecreator.format.TaskWindow;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
- * author: liana
- * data: 7/16/14.
  * Listens changes in study files and updates
  * coordinates of all the windows in current task file
  */
 public abstract class CCDocumentListener extends DocumentAdapter {
   private final TaskFile myTaskFile;
-  private int myOldLine;
-  private int myOldLineStartOffset;
-  private TaskWindow myTaskWindow;
+  private List<TaskWindowWrapper> myTaskWindows = new ArrayList<TaskWindowWrapper>();
+
 
   public CCDocumentListener(TaskFile taskFile) {
     myTaskFile = taskFile;
@@ -29,39 +28,71 @@ public abstract class CCDocumentListener extends DocumentAdapter {
   // with fragments containing "\n"
   @Override
   public void beforeDocumentChange(DocumentEvent e) {
-    int offset = e.getOffset();
-    int oldEnd = offset + e.getOldLength();
     Document document = e.getDocument();
-    myOldLine = document.getLineNumber(oldEnd);
-    myOldLineStartOffset = document.getLineStartOffset(myOldLine);
-    int line = document.getLineNumber(offset);
-    int offsetInLine = offset - document.getLineStartOffset(line);
-    LogicalPosition pos = new LogicalPosition(line, offsetInLine);
-    myTaskWindow = myTaskFile.getTaskWindow(document, pos);
+    myTaskWindows.clear();
+    for (TaskWindow taskWindow : myTaskFile.getTaskWindows()) {
+      int twStart = taskWindow.getRealStartOffset(document);
+      int length = useLength() ? taskWindow.getLength() : taskWindow.getReplacementLength();
+      int twEnd = twStart + length;
+      myTaskWindows.add(new TaskWindowWrapper(taskWindow, twStart, twEnd));
+    }
   }
 
   @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();
+      for (TaskWindowWrapper taskWindowWrapper : myTaskWindows) {
+        int twStart = taskWindowWrapper.getTwStart();
+        if (twStart > offset) {
+          twStart += change;
+        }
+        int twEnd = taskWindowWrapper.getTwEnd();
+        if (twEnd >= offset) {
+          twEnd += change;
+        }
+        TaskWindow taskWindow = taskWindowWrapper.getTaskWindow();
+        int line = document.getLineNumber(twStart);
+        int start = twStart - document.getLineStartOffset(line);
+        int length = twEnd - twStart;
+        taskWindow.setLine(line);
+        taskWindow.setStart(start);
+        if (useLength()) {
+          taskWindow.setLength(length);
+        } else {
+          taskWindow.setReplacementLength(length);
         }
-        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, useLength());
       }
+    }
   }
 
-  protected abstract void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change);
-
   protected abstract  boolean useLength();
+
+  private static class TaskWindowWrapper {
+    public TaskWindow myTaskWindow;
+    public int myTwStart;
+    public int myTwEnd;
+
+    public TaskWindowWrapper(TaskWindow taskWindow, int twStart, int twEnd) {
+      myTaskWindow = taskWindow;
+      myTwStart = twStart;
+      myTwEnd = twEnd;
+    }
+
+    public int getTwStart() {
+      return myTwStart;
+    }
+
+    public int getTwEnd() {
+      return myTwEnd;
+    }
+
+    public TaskWindow getTaskWindow() {
+      return myTaskWindow;
+    }
+  }
 }
 
index 74afc795b60a742a2ceff37b81b37fe63e92d307..24688c4b2709f3895552400e7cac9376de404df0 100644 (file)
@@ -72,12 +72,6 @@ public class CCEditorFactoryListener implements EditorFactoryListener {
       super(taskFile);
     }
 
-    @Override
-    protected void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change) {
-        int newLength = taskWindow.getReplacementLength() + change;
-        taskWindow.setReplacementLength(newLength <= 0 ? 0 : newLength);
-    }
-
     @Override
     protected boolean useLength() {
       return false;
index 951a5e85582b6b3b0d1ed975ebcfebb7fbf0b66b..e423da553d1b1b90bab773439c0c4c837a142b41 100644 (file)
@@ -85,6 +85,7 @@ public class CCAddTaskWindow extends DumbAwareAction {
     }
     int index = taskFile.getTaskWindows().size() + 1;
     taskFile.addTaskWindow(taskWindow, index);
+    taskFile.sortTaskWindows();
     taskWindow.drawHighlighter(editor, false);
     taskWindow.createGuardedBlocks(editor);
   }
index c201e4ddaee44741e0aff9665ecd15ae1dec64f2..b5a0292db68496700498121ca6bebca270449e9d 100644 (file)
@@ -134,6 +134,9 @@ public class CCCreateCourseArchive extends DumbAwareAction {
     final TaskFile taskFile = taskFiles.getValue();
     TaskFile taskFileSaved = new TaskFile();
     taskFile.copy(taskFileSaved);
+    for (TaskWindow taskWindow : taskFile.getTaskWindows()) {
+      taskWindow.setLength(taskWindow.getReplacementLength());
+    }
     CommandProcessor.getInstance().executeCommand(project, new Runnable() {
       @Override
       public void run() {
@@ -168,7 +171,7 @@ public class CCCreateCourseArchive extends DumbAwareAction {
         ApplicationManager.getApplication().runWriteAction(new Runnable() {
           @Override
           public void run() {
-            document.replaceString(offset, offset + taskWindow.getReplacementLength(), taskText);
+            document.replaceString(offset, offset + taskWindow.getLength(), taskText);
             FileDocumentManager.getInstance().saveDocument(document);
           }
         });
@@ -254,11 +257,6 @@ public class CCCreateCourseArchive extends DumbAwareAction {
       super(taskFile);
     }
 
-    @Override
-    protected void updateTaskWindowLength(CharSequence fragment, TaskWindow taskWindow, int change) {
-      //we don't need to update task window length
-    }
-
     @Override
     protected boolean useLength() {
       return true;
index c48a4f41d7e157672048ab82bdf7ea328b5f5f4d..9fb10eaa179a6352ee6b10ccfc005d3247b210f3 100644 (file)
@@ -6,9 +6,9 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.LogicalPosition;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.coursecreator.CCProjectService;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class TaskFile {
@@ -57,52 +57,6 @@ public class TaskFile {
     return null;
   }
 
-  /**
-   * Updates task window lines
-   *
-   * @param startLine lines greater than this line and including this line will be updated
-   * @param change    change to be added to line numbers
-   */
-  public void incrementLines(int startLine, int change) {
-    for (TaskWindow taskTaskWindow : task_windows) {
-      if (taskTaskWindow.getLine() >= startLine) {
-        taskTaskWindow.setLine(taskTaskWindow.getLine() + change);
-      }
-    }
-  }
-
-  /**
-   * Updates windows in specific line
-   *
-   * @param lineChange         change in line number
-   * @param line               line to be updated
-   * @param newEndOffsetInLine distance from line start to end of inserted fragment
-   * @param oldEndOffsetInLine distance from line start to end of changed fragment
-   */
-  public void updateLine(int lineChange, int line, int newEndOffsetInLine, int oldEndOffsetInLine, boolean useLength) {
-    for (TaskWindow w : task_windows) {
-      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 - 1);
-          if (prevTW.getLine() == line) {
-            int prevLength = useLength ? prevTW.getLength() : prevTW.getReplacementLength();
-            int endOffset = prevTW.getStart() + prevLength;
-            if (endOffset >= newEndOffsetInLine) {
-              coveredByPrevTW = true;
-            }
-          }
-        }
-        if (lineChange != 0 || newEndOffsetInLine <= w.getStart() || coveredByPrevTW) {
-          w.setStart(distance + newEndOffsetInLine);
-          w.setLine(line + lineChange);
-        }
-      }
-    }
-  }
-
   public void copy(@NotNull final TaskFile target) {
     target.setIndex(myIndex);
     for (TaskWindow taskWindow : task_windows) {
@@ -110,6 +64,7 @@ public class TaskFile {
                                               taskWindow.getLength(), "");
       target.getTaskWindows().add(savedWindow);
       savedWindow.setIndex(taskWindow.getIndex());
+      savedWindow.setReplacementLength(taskWindow.getReplacementLength());
     }
   }
 
@@ -121,6 +76,8 @@ public class TaskFile {
       }
       taskWindowUpdated.setLine(taskWindow.getLine());
       taskWindowUpdated.setStart(taskWindow.getStart());
+      taskWindowUpdated.setReplacementLength(taskWindow.getReplacementLength());
+      taskWindowUpdated.setLength(taskWindow.getLength());
     }
   }
 
@@ -142,4 +99,11 @@ public class TaskFile {
       taskWindow.createGuardedBlocks(editor);
     }
   }
+
+  public void sortTaskWindows() {
+    Collections.sort(task_windows);
+    for (int i = 0; i < task_windows.size(); i++) {
+      task_windows.get(i).setIndex(i + 1);
+    }
+  }
 }
index dc7551929e30a505a2e12a5ef2b868ab662327e8..385aaeddf26e444ed735ff7895a90c97809a11e2 100644 (file)
@@ -20,7 +20,7 @@ import org.jetbrains.plugins.coursecreator.CCProjectService;
 import java.io.File;
 import java.util.List;
 
-public class TaskWindow implements Comparable{
+public class TaskWindow implements Comparable<TaskWindow> {
 
   @Expose public int line;
   @Expose public int start;
@@ -120,8 +120,7 @@ public class TaskWindow implements Comparable{
   }
 
   @Override
-  public int compareTo(Object o) {
-    TaskWindow taskWindow = (TaskWindow)o;
+  public int compareTo(@NotNull TaskWindow taskWindow) {
     int lineDiff = line - taskWindow.line;
     if (lineDiff == 0) {
       return start - taskWindow.start;
@@ -154,4 +153,8 @@ public class TaskWindow implements Comparable{
       .addRangeHighlighter(start, end, HighlighterLayer.LAST + 1, null, HighlighterTargetArea.EXACT_RANGE);
     blocks.add(rh);
   }
+
+  public void setLength(int length) {
+    this.length = length;
+  }
 }
\ No newline at end of file
index 8955032aa4085ae0120b3321b52605797d33f266..848becfae1b1dbacaee7158588bbfe642fb83dde 100644 (file)
@@ -2,22 +2,22 @@ package com.jetbrains.python.edu;
 
 
 import com.intellij.openapi.editor.Document;
-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.jetbrains.python.edu.course.TaskFile;
 import com.jetbrains.python.edu.course.TaskWindow;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Listens changes in study files and updates
  * coordinates of all the windows in current task file
  */
 public class StudyDocumentListener extends DocumentAdapter {
   private final TaskFile myTaskFile;
-  private int myOldLine;
-  private int myOldLineStartOffset;
-  private TaskWindow myTaskWindow;
+  private List<TaskWindowWrapper> myTaskWindows = new ArrayList<TaskWindowWrapper>();
 
   public StudyDocumentListener(TaskFile taskFile) {
     myTaskFile = taskFile;
@@ -28,15 +28,13 @@ public class StudyDocumentListener extends DocumentAdapter {
   // with fragments containing "\n"
   @Override
   public void beforeDocumentChange(DocumentEvent e) {
-    int offset = e.getOffset();
-    int oldEnd = offset + e.getOldLength();
     Document document = e.getDocument();
-    myOldLine = document.getLineNumber(oldEnd);
-    myOldLineStartOffset = document.getLineStartOffset(myOldLine);
-    int line = document.getLineNumber(offset);
-    int offsetInLine = offset - document.getLineStartOffset(line);
-    LogicalPosition pos = new LogicalPosition(line, offsetInLine);
-    myTaskWindow = myTaskFile.getTaskWindow(document, pos);
+    myTaskWindows.clear();
+    for (TaskWindow taskWindow : myTaskFile.getTaskWindows()) {
+      int twStart = taskWindow.getRealStartOffset(document);
+      int twEnd = twStart + taskWindow.getLength();
+      myTaskWindows.add(new TaskWindowWrapper(taskWindow, twStart, twEnd));
+    }
   }
 
   @Override
@@ -46,17 +44,47 @@ public class StudyDocumentListener extends DocumentAdapter {
       Document document = e.getDocument();
       int offset = e.getOffset();
       int change = event.getNewLength() - event.getOldLength();
-      if (myTaskWindow != null) {
-        int newLength = myTaskWindow.getLength() + change;
-        myTaskWindow.setLength(newLength <= 0 ? 0 : newLength);
+      for (TaskWindowWrapper taskWindowWrapper : myTaskWindows) {
+        int twStart = taskWindowWrapper.getTwStart();
+        if (twStart > offset) {
+          twStart += change;
+        }
+        int twEnd = taskWindowWrapper.getTwEnd();
+        if (twEnd >= offset) {
+          twEnd += change;
+        }
+        TaskWindow taskWindow = taskWindowWrapper.getTaskWindow();
+        int line = document.getLineNumber(twStart);
+        int start = twStart - document.getLineStartOffset(line);
+        int length = twEnd - twStart;
+        taskWindow.setLine(line);
+        taskWindow.setStart(start);
+        taskWindow.setLength(length);
       }
-      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);
+    }
+  }
+
+  private static class TaskWindowWrapper {
+    public TaskWindow myTaskWindow;
+    public int myTwStart;
+    public int myTwEnd;
+
+    public TaskWindowWrapper(TaskWindow taskWindow, int twStart, int twEnd) {
+      myTaskWindow = taskWindow;
+      myTwStart = twStart;
+      myTwEnd = twEnd;
+    }
+
+    public int getTwStart() {
+      return myTwStart;
+    }
+
+    public int getTwEnd() {
+      return myTwEnd;
+    }
+
+    public TaskWindow getTaskWindow() {
+      return myTaskWindow;
     }
   }
 }
index aaaef375a093405e9b4c7c350aa92d982869736b..e9281e957855cc507e60dee2ac8f455285e8a9c1 100644 (file)
@@ -127,20 +127,6 @@ public class TaskFile implements Stateful {
     return null;
   }
 
-  /**
-   * Updates task window lines
-   *
-   * @param startLine lines greater than this line and including this line will be updated
-   * @param change    change to be added to line numbers
-   */
-  public void incrementLines(int startLine, int change) {
-    for (TaskWindow taskTaskWindow : taskWindows) {
-      if (taskTaskWindow.getLine() >= startLine) {
-        taskTaskWindow.setLine(taskTaskWindow.getLine() + change);
-      }
-    }
-  }
-
   /**
    * Initializes state of task file
    *
@@ -165,36 +151,6 @@ public class TaskFile implements Stateful {
     myIndex = index;
   }
 
-  /**
-   * Updates windows in specific line
-   *
-   * @param lineChange         change in line number
-   * @param line               line to be updated
-   * @param newEndOffsetInLine distance from line start to end of inserted fragment
-   * @param oldEndOffsetInLine distance from line start to end of changed fragment
-   */
-  public void updateLine(int lineChange, int line, int newEndOffsetInLine, int oldEndOffsetInLine) {
-    for (TaskWindow w : taskWindows) {
-      if ((w.getLine() == line) && (w.getStart() > oldEndOffsetInLine)) {
-        int distance = w.getStart() - oldEndOffsetInLine;
-        boolean coveredByPrevTW = false;
-        int prevIndex = w.getIndex() - 1;
-        if (StudyUtils.indexIsValid(prevIndex, taskWindows)) {
-          TaskWindow prevTW = taskWindows.get(prevIndex);
-          if (prevTW.getLine() == line) {
-            int endOffset = prevTW.getStart() + prevTW.getLength();
-            if (endOffset >= newEndOffsetInLine) {
-              coveredByPrevTW = true;
-            }
-          }
-        }
-        if (lineChange != 0 || newEndOffsetInLine <= w.getStart() || coveredByPrevTW) {
-          w.setStart(distance + newEndOffsetInLine);
-          w.setLine(line + lineChange);
-        }
-      }
-    }
-  }
 
   public static void copy(@NotNull final TaskFile source, @NotNull final TaskFile target) {
     List<TaskWindow> sourceTaskWindows = source.getTaskWindows();