IDEA-85100 Deleting wrapped lines with Ctrl+Y doen't work properly with "soft wrapped" lines

This commit is contained in:
Denis.Zhdanov
2012-05-11 09:43:30 +04:00
parent 983bbb5b76
commit 28ff5f0241
6 changed files with 80 additions and 60 deletions
@@ -47,7 +47,7 @@ public class NamedElementDuplicateHandler extends EditorWriteActionHandler {
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (file != null) {
VisualPosition caret = editor.getCaretModel().getVisualPosition();
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLinesRange(editor, caret, caret);
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcSurroundingRange(editor, caret, caret);
TextRange toDuplicate = new TextRange(editor.logicalPositionToOffset(lines.first), editor.logicalPositionToOffset(lines.second));
PsiElement name = findNameIdentifier(editor, file, toDuplicate);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,44 +53,8 @@ public class DeleteLineAction extends TextComponentEditorAction {
document.deleteString(lineStartOffset, nextLineStartOffset);
return;
}
deleteLineAtCaret(editor);
editor.getSelectionModel().selectLineAtCaret();
EditorModificationUtil.deleteSelectedText(editor);
}
}
public static void deleteLineAtCaret(Editor editor) {
LogicalPosition logicalPosition = editor.getCaretModel().getLogicalPosition();
int lineNumber = logicalPosition.line;
Document document = editor.getDocument();
if (lineNumber >= document.getLineCount())
return;
if (lineNumber == document.getLineCount() - 1){
if (document.getLineCount() > 0 && lineNumber > 0){
int start = document.getLineEndOffset(lineNumber - 1);
int end = document.getLineEndOffset(lineNumber) + document.getLineSeparatorLength(lineNumber);
document.deleteString(start, end);
LogicalPosition pos = new LogicalPosition(lineNumber - 1, logicalPosition.column);
editor.getCaretModel().moveToLogicalPosition(pos);
}
else{
document.deleteString(0, document.getTextLength());
editor.getCaretModel().moveToOffset(0);
}
}
else{
VisualPosition caretPosition = editor.getCaretModel().getVisualPosition();
VisualPosition thisLineVisible = new VisualPosition(caretPosition.line, 0);
LogicalPosition thisLineLogical = editor.visualToLogicalPosition(thisLineVisible);
VisualPosition nextLineVisible = new VisualPosition(caretPosition.line + 1, 0);
LogicalPosition nextLineLogical = editor.visualToLogicalPosition(nextLineVisible);
int startOffset = editor.logicalPositionToOffset(thisLineLogical);
int endOffset = editor.logicalPositionToOffset(nextLineLogical);
document.deleteString(startOffset, endOffset);
}
editor.getCaretModel().moveToLogicalPosition(logicalPosition);
editor.getSelectionModel().removeSelection();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -69,7 +69,7 @@ public class DuplicateAction extends EditorAction {
}
static Pair<Integer, Integer> duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) {
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLinesRange(editor, rangeStart, rangeEnd);
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd);
int offset = editor.getCaretModel().getOffset();
LogicalPosition lineStart = lines.first;
@@ -651,32 +651,77 @@ public class EditorUtil {
return result;
}
public static Pair<LogicalPosition, LogicalPosition> calcCaretLinesRange(Editor editor) {
return calcCaretLinesRange(editor, editor.getCaretModel().getVisualPosition(), editor.getCaretModel().getVisualPosition());
/**
* Delegates to the {@link #calcSurroundingRange(Editor, VisualPosition, VisualPosition)} with the
* {@link CaretModel#getVisualPosition() caret visual position} as an argument.
*
* @param editor target editor
* @return surrounding logical positions
* @see #calcSurroundingRange(Editor, VisualPosition, VisualPosition)
*/
public static Pair<LogicalPosition, LogicalPosition> calcCaretLineRange(Editor editor) {
return calcSurroundingRange(editor, editor.getCaretModel().getVisualPosition(), editor.getCaretModel().getVisualPosition());
}
/**
* Calculates the closest non-soft-wrapped logical positions for current caret position.
* Calculates logical positions that surround given visual positions and conform to the following criteria:
* <pre>
* <ul>
* <li>located at the start or the end of the visual line;</li>
* <li>doesn't have soft wrap at the target offset;</li>
* </ul>
* </pre>
* Example:
* <pre>
* first line [soft-wrap] some [start-position] text [end-position] [fold-start] fold line 1
* fold line 2
* fold line 3[fold-end] [soft-wrap] end text
* </pre>
* The very first and the last positions will be returned here.
*
* @param editor target editor to use
* @param start target start coordinate
* @param end target end coordinate
* @return pair of non-soft-wrapped logical positions closest to the caret position of the given editor
* @return pair of the closest surrounding non-soft-wrapped logical positions for the visual line start and end
*/
public static Pair<LogicalPosition, LogicalPosition> calcCaretLinesRange(Editor editor, VisualPosition start, VisualPosition end) {
int visualLine = start.line;
@SuppressWarnings("AssignmentToForLoopParameter")
public static Pair<LogicalPosition, LogicalPosition> calcSurroundingRange(Editor editor, VisualPosition start, VisualPosition end) {
final Document document = editor.getDocument();
final FoldingModel foldingModel = editor.getFoldingModel();
LogicalPosition lineStart = editor.visualToLogicalPosition(new VisualPosition(visualLine, 0));
while (lineStart.softWrapLinesOnCurrentLogicalLine > 0) {
lineStart = editor.visualToLogicalPosition(new VisualPosition(--visualLine, 0));
LogicalPosition first = editor.visualToLogicalPosition(new VisualPosition(start.line, 0));
for (
int line = first.line, offset = document.getLineStartOffset(line);
offset > 0;
offset = document.getLineStartOffset(line))
{
final FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(offset);
if (foldRegion == null) {
first = new LogicalPosition(line, 0);
break;
}
line = document.getLineNumber(foldRegion.getStartOffset());
}
visualLine = end.line + 1;
LogicalPosition nextLineStart = editor.visualToLogicalPosition(new VisualPosition(end.line + 1, 0));
while (nextLineStart.line == lineStart.line) {
nextLineStart = editor.visualToLogicalPosition(new VisualPosition(++visualLine, 0));
LogicalPosition second = editor.visualToLogicalPosition(new VisualPosition(end.line, 0));
for (
int line = second.line, offset = document.getLineEndOffset(line);
offset <= document.getTextLength();
offset = document.getLineEndOffset(line))
{
final FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(offset);
if (foldRegion == null) {
second = new LogicalPosition(line + 1, 0);
break;
}
line = document.getLineNumber(foldRegion.getEndOffset());
}
return new Pair<LogicalPosition, LogicalPosition>(lineStart, nextLineStart);
if (second.line >= document.getLineCount()) {
second = editor.offsetToLogicalPosition(document.getTextLength());
}
return new Pair<LogicalPosition, LogicalPosition>(first, second);
}
public static void scrollToTheEnd(final Editor editor) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -721,7 +721,7 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
return;
}
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLinesRange(myEditor);
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLineRange(myEditor);
LogicalPosition lineStart = lines.first;
LogicalPosition nextLineStart = lines.second;
@@ -293,7 +293,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"This a long string that is expected to be wrapped in more than one visual line<caret>";
init(20, text);
List<? extends SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
backspace();
@@ -307,7 +307,7 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
"Long line2 that is expected to be soft-wrapped<caret>";
init(20, text);
List<? extends SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
List<SoftWrap> softWrapsBeforeModification = new ArrayList<SoftWrap>(getSoftWrapModel().getRegisteredSoftWraps());
assertTrue(softWrapsBeforeModification.size() > 0);
int offset = myEditor.getCaretModel().getOffset();
@@ -968,6 +968,17 @@ public class SoftWrapApplianceOnDocumentModificationTest extends AbstractEditorP
delete();
assertEquals("text 234", myEditor.getDocument().getText());
}
public void testSelectionOfLineWithSoftWrapAndFoldRegion() throws IOException {
final String text =
"123\n" +
"fold line 1\n" +
"fold line 2 456";
init(6, text);
addCollapsedFoldRegion(2, text.indexOf("4"), "...");
myEditor.getSelectionModel().selectLineAtCaret();
assertEquals(text, myEditor.getSelectionModel().getSelectedText());
}
private void init(final int visibleWidthInColumns, @NotNull String fileText) throws IOException {
int symbolWidthInPixels = 7;