blob: d2c3df51609a07108e887f9dae61d627644fb6ca [file] [log] [blame]
/*
* Copyright 2000-2014 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.
*/
/*
* Created by IntelliJ IDEA.
* User: max
* Date: May 14, 2002
* Time: 7:18:30 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.Nullable;
public class DuplicateAction extends EditorAction {
public DuplicateAction() {
super(new Handler());
}
private static class Handler extends EditorWriteActionHandler {
public Handler() {
super(true);
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
duplicateLineOrSelectedBlockAtCaret(editor);
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return !editor.isOneLineMode() || editor.getSelectionModel().hasSelection();
}
}
private static void duplicateLineOrSelectedBlockAtCaret(Editor editor) {
Document document = editor.getDocument();
CaretModel caretModel = editor.getCaretModel();
ScrollingModel scrollingModel = editor.getScrollingModel();
if(editor.getSelectionModel().hasSelection()) {
int start = editor.getSelectionModel().getSelectionStart();
int end = editor.getSelectionModel().getSelectionEnd();
String s = document.getCharsSequence().subSequence(start, end).toString();
document.insertString(end, s);
caretModel.moveToOffset(end+s.length());
scrollingModel.scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
editor.getSelectionModel().setSelection(end, end+s.length());
}
else {
duplicateLinesRange(editor, document, caretModel.getVisualPosition(), caretModel.getVisualPosition());
}
}
@Nullable
static Couple<Integer> duplicateLinesRange(Editor editor, Document document, VisualPosition rangeStart, VisualPosition rangeEnd) {
Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcSurroundingRange(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);
if (end <= start) {
return null;
}
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 */
|| lineStart.line == document.getLineCount() - 1 /* last line*/
|| document.getLineSeparatorLength(lineToCheck) == 0)
{
s = "\n"+s;
newOffset++;
}
document.insertString(end, s);
editor.getCaretModel().moveToOffset(newOffset);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
return Couple.of(end, end + s.length() - 1); // don't include separator of last line in range to select
}
@Override
public void update(final Editor editor, final Presentation presentation, final DataContext dataContext) {
super.update(editor, presentation, dataContext);
if (editor.getSelectionModel().hasSelection()) {
presentation.setText(EditorBundle.message("action.duplicate.block"), true);
}
else {
presentation.setText(EditorBundle.message("action.duplicate.line"), true);
}
}
}