don't update selection on document changes in bulk mode (IDEA-153495)

This commit is contained in:
Dmitry Batrak
2016-03-25 17:57:10 +03:00
parent 9d6f571065
commit dfdf234ea3
3 changed files with 41 additions and 12 deletions
@@ -125,6 +125,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable {
Document doc = myEditor.getDocument();
if (myOffset > doc.getTextLength() || savedBeforeBulkCaretMarker != null) return;
savedBeforeBulkCaretMarker = doc.createRangeMarker(myOffset, myOffset);
beforeDocumentChange();
}
void onBulkDocumentUpdateFinished() {
@@ -142,6 +143,7 @@ public class CaretImpl extends UserDataHolderBase implements Caret, Dumpable {
}
releaseBulkCaretMarker();
}
documentChanged();
}
public void beforeDocumentChange() {
@@ -53,15 +53,13 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
private TextAttributes myTextAttributes;
private DocumentEvent myIsInUpdate;
public SelectionModelImpl(EditorImpl editor) {
myEditor = editor;
}
@Override
public void beforeDocumentChange(DocumentEvent event) {
myIsInUpdate = event;
if (myEditor.getDocument().isInBulkUpdate()) return;
for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
((CaretImpl)caret).beforeDocumentChange();
}
@@ -69,16 +67,14 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
@Override
public void documentChanged(DocumentEvent event) {
if (myIsInUpdate == event) {
myIsInUpdate = null;
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
public void run() {
for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
((CaretImpl)caret).documentChanged();
}
if (myEditor.getDocument().isInBulkUpdate()) return;
myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
public void run() {
for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
((CaretImpl)caret).documentChanged();
}
});
}
}
});
}
@Override
@@ -22,6 +22,10 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.event.CaretAdapter;
import com.intellij.openapi.editor.event.CaretEvent;
import com.intellij.openapi.editor.event.SelectionEvent;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
@@ -329,4 +333,31 @@ public class EditorImplTest extends AbstractEditorTest {
Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
assertTrue(visibleArea.contains(caretPoint));
}
public void testCaretAndSelectionEventsInBulkMode() throws Exception {
initText("abc<selection>def<caret></selection>");
StringBuilder output = new StringBuilder();
CaretAdapter caretListener = new CaretAdapter() {
@Override
public void caretPositionChanged(CaretEvent e) {
output.append("caret:").append(e.getNewPosition());
}
};
SelectionListener selectionListener = new SelectionListener() {
@Override
public void selectionChanged(SelectionEvent e) {
output.append("selection:").append(e.getNewRange());
}
};
myEditor.getCaretModel().addCaretListener(caretListener);
myEditor.getSelectionModel().addSelectionListener(selectionListener);
((DocumentEx)myEditor.getDocument()).setInBulkUpdate(true);
WriteCommandAction.runWriteCommandAction(ourProject, () -> {myEditor.getDocument().insertString(0, " ");});
assertEquals("", output.toString());
((DocumentEx)myEditor.getDocument()).setInBulkUpdate(false);
myEditor.getSelectionModel().removeSelectionListener(selectionListener);
myEditor.getCaretModel().removeCaretListener(caretListener);
assertEquals("caret:LogicalPosition: (0, 7)selection:(4,7)", output.toString());
checkResultByText(" abc<selection>def<caret></selection>");
}
}