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 34dc39f1b531..50749c166843 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 @@ -62,29 +62,34 @@ public class DuplicateAction extends EditorAction { editor.getSelectionModel().setSelection(end, end+s.length()); } else { - Pair lines = EditorUtil.calcCaretLinesRange(editor); - int offset = caretModel.getOffset(); - - LogicalPosition lineStart = lines.first; - LogicalPosition nextLineStart = lines.second; - int start = editor.logicalPositionToOffset(lineStart); - int end = editor.logicalPositionToOffset(nextLineStart); - String s = document.getCharsSequence().subSequence(start, end).toString(); - final int lineToCheck = nextLineStart.line - 1; - - int newOffset = end + offset - start; - if(lineToCheck == document.getLineCount () /*empty document*/ || - document.getLineSeparatorLength(lineToCheck) == 0) { - s = "\n"+s; - newOffset++; - } - document.insertString(end, s); - - caretModel.moveToOffset(newOffset); - scrollingModel.scrollToCaret(ScrollType.RELATIVE); + duplicateLinesRange(editor, document, caretModel.getVisualPosition(), caretModel.getVisualPosition()); } } + static Pair duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) { + Pair lines = EditorUtil.calcCaretLinesRange(editor, rangeStart, rangeEnd); + int offset = editor.getCaretModel().getOffset(); + + LogicalPosition lineStart = lines.first; + LogicalPosition nextLineStart = lines.second; + int start = editor.logicalPositionToOffset(lineStart); + int end = editor.logicalPositionToOffset(nextLineStart); + String s = document.getCharsSequence().subSequence(start, end).toString(); + final int lineToCheck = nextLineStart.line - 1; + + int newOffset = end + offset - start; + if(lineToCheck == document.getLineCount () /*empty document*/ || + document.getLineSeparatorLength(lineToCheck) == 0) { + s = "\n"+s; + newOffset++; + } + document.insertString(end, s); + + editor.getCaretModel().moveToOffset(newOffset); + editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); + return new Pair(end, end+s.length()); + } + @Override public void update(final Editor editor, final Presentation presentation, final DataContext dataContext) { super.update(editor, presentation, dataContext); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java new file mode 100644 index 000000000000..fc3c86c50aed --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2010 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.actions; + +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.editor.actionSystem.EditorAction; +import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; +import com.intellij.openapi.util.Pair; + +/** + * @author yole + */ +public class DuplicateLinesAction extends EditorAction { + public DuplicateLinesAction() { + super(new Handler()); + } + + private static class Handler extends EditorWriteActionHandler { + @Override + public void executeWriteAction(Editor editor, DataContext dataContext) { + if (editor.getSelectionModel().hasSelection()) { + int selStart = editor.getSelectionModel().getSelectionStart(); + int selEnd = editor.getSelectionModel().getSelectionEnd(); + VisualPosition rangeStart = editor.offsetToVisualPosition(Math.min(selStart, selEnd)); + VisualPosition rangeEnd = editor.offsetToVisualPosition(Math.max(selStart, selEnd)); + final Pair copiedRange = + DuplicateAction.duplicateLinesRange(editor, editor.getDocument(), rangeStart, rangeEnd); + editor.getSelectionModel().setSelection(copiedRange.first, copiedRange.second); + } + else { + VisualPosition caretPos = editor.getCaretModel().getVisualPosition(); + DuplicateAction.duplicateLinesRange(editor, editor.getDocument(), caretPos, caretPos); + } + } + } +} 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 bc5b87810c7a..4db50963e5b8 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 @@ -544,23 +544,26 @@ public class EditorUtil { return result; } + public static Pair calcCaretLinesRange(Editor editor) { + return calcCaretLinesRange(editor, editor.getCaretModel().getVisualPosition(), editor.getCaretModel().getVisualPosition()); + } + /** * Calculates the closest non-soft-wrapped logical positions for current caret position. * * @param editor target editor to use * @return pair of non-soft-wrapped logical positions closest to the caret position of the given editor */ - public static Pair calcCaretLinesRange(Editor editor) { - VisualPosition caret = editor.getCaretModel().getVisualPosition(); - int visualLine = caret.line; + public static Pair calcCaretLinesRange(Editor editor, VisualPosition start, VisualPosition end) { + int visualLine = start.line; LogicalPosition lineStart = editor.visualToLogicalPosition(new VisualPosition(visualLine, 0)); while (lineStart.softWrapLinesOnCurrentLogicalLine > 0) { lineStart = editor.visualToLogicalPosition(new VisualPosition(--visualLine, 0)); } - visualLine = caret.line + 1; - LogicalPosition nextLineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line + 1, 0)); + 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)); } diff --git a/platform/platform-resources/src/idea/Keymap_Eclipse.xml b/platform/platform-resources/src/idea/Keymap_Eclipse.xml index 838b49947ae1..7198e1f92409 100644 --- a/platform/platform-resources/src/idea/Keymap_Eclipse.xml +++ b/platform/platform-resources/src/idea/Keymap_Eclipse.xml @@ -65,8 +65,7 @@ - - + diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 2f90dfb46abd..55c40538ce57 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -71,6 +71,7 @@ +