diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java index 9c65977e5f6e..326e9ff2fde9 100644 --- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java +++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java @@ -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 lines = EditorUtil.calcCaretLinesRange(editor, caret, caret); + Pair lines = EditorUtil.calcSurroundingRange(editor, caret, caret); TextRange toDuplicate = new TextRange(editor.logicalPositionToOffset(lines.first), editor.logicalPositionToOffset(lines.second)); PsiElement name = findNameIdentifier(editor, file, toDuplicate); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java index b8eb56eb84e5..4f29a9e4e2e2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java @@ -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(); - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java index 2e647d98a477..72a05fb0fc29 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java @@ -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 duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) { - Pair lines = EditorUtil.calcCaretLinesRange(editor, rangeStart, rangeEnd); + Pair lines = EditorUtil.calcSurroundingRange(editor, rangeStart, rangeEnd); int offset = editor.getCaretModel().getOffset(); LogicalPosition lineStart = lines.first; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index 4cf9d1dfc587..07a4654578ab 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -651,32 +651,77 @@ public class EditorUtil { return result; } - public static Pair 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 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: + *
+   * 
    + *
  • located at the start or the end of the visual line;
  • + *
  • doesn't have soft wrap at the target offset;
  • + *
+ *
+ * Example: + *
+   *   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
+   * 
+ * 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 calcCaretLinesRange(Editor editor, VisualPosition start, VisualPosition end) { - int visualLine = start.line; + @SuppressWarnings("AssignmentToForLoopParameter") + public static Pair 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(lineStart, nextLineStart); + + if (second.line >= document.getLineCount()) { + second = editor.offsetToLogicalPosition(document.getTextLength()); + } + return new Pair(first, second); } public static void scrollToTheEnd(final Editor editor) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java index 935d18d64886..72d167196289 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java @@ -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 lines = EditorUtil.calcCaretLinesRange(myEditor); + Pair lines = EditorUtil.calcCaretLineRange(myEditor); LogicalPosition lineStart = lines.first; LogicalPosition nextLineStart = lines.second; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java index c2e95e03e9f5..6b4342aeadb0 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java @@ -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"; init(20, text); - List softWrapsBeforeModification = new ArrayList(getSoftWrapModel().getRegisteredSoftWraps()); + List softWrapsBeforeModification = new ArrayList(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"; init(20, text); - List softWrapsBeforeModification = new ArrayList(getSoftWrapModel().getRegisteredSoftWraps()); + List softWrapsBeforeModification = new ArrayList(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;