mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fixed EDU-233, switched to flat model in offset listener
This commit is contained in:
+60
-29
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-6
@@ -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;
|
||||
|
||||
+1
@@ -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);
|
||||
}
|
||||
|
||||
+4
-6
@@ -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;
|
||||
|
||||
+11
-47
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user