duplicate lines action (IDEA-56385)

This commit is contained in:
Dmitry Jemerov
2010-11-03 19:08:46 +03:00
parent 4cf4a635b5
commit eaf9b562fa
5 changed files with 86 additions and 27 deletions
@@ -62,29 +62,34 @@ public class DuplicateAction extends EditorAction {
editor.getSelectionModel().setSelection(end, end+s.length());
}
else {
Pair<LogicalPosition, LogicalPosition> 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<Integer, Integer> duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) {
Pair<LogicalPosition, LogicalPosition> 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<Integer, Integer>(end, end+s.length());
}
@Override
public void update(final Editor editor, final Presentation presentation, final DataContext dataContext) {
super.update(editor, presentation, dataContext);
@@ -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<Integer,Integer> 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);
}
}
}
}
@@ -544,23 +544,26 @@ public class EditorUtil {
return result;
}
public static Pair<LogicalPosition, LogicalPosition> 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<LogicalPosition, LogicalPosition> calcCaretLinesRange(Editor editor) {
VisualPosition caret = editor.getCaretModel().getVisualPosition();
int visualLine = caret.line;
public static Pair<LogicalPosition, LogicalPosition> 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));
}
@@ -65,8 +65,7 @@
<action id="EditorDeleteLine">
<keyboard-shortcut first-keystroke="control D" />
</action>
<action id="EditorDuplicate">
<keyboard-shortcut first-keystroke="control alt UP" />
<action id="EditorDuplicateLines">
<keyboard-shortcut first-keystroke="control alt DOWN" />
</action>
<action id="EditorIndentSelection">
@@ -71,6 +71,7 @@
<action id="EditorDeleteToWordEnd" class="com.intellij.openapi.editor.actions.DeleteToWordEndAction"/>
<action id="EditorDeleteLine" class="com.intellij.openapi.editor.actions.DeleteLineAction"/>
<action id="EditorDuplicate" class="com.intellij.openapi.editor.actions.DuplicateAction"/>
<action id="EditorDuplicateLines" class="com.intellij.openapi.editor.actions.DuplicateLinesAction"/>
<action id="EditorToggleInsertState" class="com.intellij.openapi.editor.actions.ToggleInsertStateAction"/>
<action id="EditorToggleColumnMode" class="com.intellij.openapi.editor.actions.ToggleColumnModeAction"/>
<action id="EditorToggleShowWhitespaces" class="com.intellij.openapi.editor.actions.ToggleShowWhitespacesAction"/>