Make EditorToggleColumnMode action work with multiple carets like previously with block selection (IDEA-80056)

This commit is contained in:
Dmitry Batrak
2014-02-25 13:50:16 +04:00
parent eb39a650bf
commit e58ef02791
6 changed files with 156 additions and 22 deletions
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.Segment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
/**
@@ -186,7 +185,7 @@ public interface CaretModel {
* Returns all carets currently existing in the document, ordered by their position in the document.
*/
@NotNull
Collection<Caret> getAllCarets();
List<Caret> getAllCarets();
/**
* Returns a caret at the given position in the document, or <code>null</code>, if there's no caret there.
@@ -165,9 +165,9 @@ public class CaretModelWindow implements CaretModel {
@NotNull
@Override
public Collection<Caret> getAllCarets() {
Collection<Caret> hostCarets = myDelegate.getAllCarets();
Collection<Caret> carets = new ArrayList<Caret>(hostCarets.size());
public List<Caret> getAllCarets() {
List<Caret> hostCarets = myDelegate.getAllCarets();
List<Caret> carets = new ArrayList<Caret>(hostCarets.size());
for (Caret hostCaret : hostCarets) {
carets.add(createInjectedCaret(hostCaret));
}
@@ -27,50 +27,74 @@ package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.DumbAware;
import java.util.List;
public class ToggleColumnModeAction extends ToggleAction implements DumbAware {
@Override
public void setSelected(AnActionEvent e, boolean state) {
final EditorEx editor = getEditor(e);
if (editor.getCaretModel().supportsMultipleCarets()) {
editor.setColumnMode(state);
return;
}
final SelectionModel selectionModel = editor.getSelectionModel();
final CaretModel caretModel = editor.getCaretModel();
if (state) {
boolean hasSelection = selectionModel.hasSelection();
boolean hasSelection = caretModel.getAllCarets().size() == 1 && selectionModel.hasSelection();
int selStart = selectionModel.getSelectionStart();
int selEnd = selectionModel.getSelectionEnd();
final CaretModel caretModel = editor.getCaretModel();
LogicalPosition blockStart = selStart == caretModel.getOffset()
LogicalPosition blockStart, blockEnd;
if (caretModel.supportsMultipleCarets()) {
LogicalPosition logicalSelStart = editor.offsetToLogicalPosition(selStart);
LogicalPosition logicalSelEnd = editor.offsetToLogicalPosition(selEnd);
int caretOffset = caretModel.getOffset();
blockStart = selStart == caretOffset ? logicalSelEnd : logicalSelStart;
blockEnd = selStart == caretOffset ? logicalSelStart : logicalSelEnd;
}
else {
blockStart = selStart == caretModel.getOffset()
? caretModel.getLogicalPosition()
: editor.offsetToLogicalPosition(selStart);
blockEnd = selEnd == caretModel.getOffset()
? caretModel.getLogicalPosition()
: editor.offsetToLogicalPosition(selStart);
LogicalPosition blockEnd = selEnd == caretModel.getOffset()
? caretModel.getLogicalPosition()
: editor.offsetToLogicalPosition(selEnd);
: editor.offsetToLogicalPosition(selEnd);
}
editor.setColumnMode(true);
if (hasSelection) {
selectionModel.setBlockSelection(blockStart, blockEnd);
}
else {
else if (!caretModel.supportsMultipleCarets()) {
selectionModel.removeSelection();
}
}
else {
final boolean hasSelection = selectionModel.hasBlockSelection();
boolean hasSelection = selectionModel.hasBlockSelection();
final LogicalPosition blockStart = selectionModel.getBlockStart();
final LogicalPosition blockEnd = selectionModel.getBlockEnd();
int selStart = hasSelection && blockStart != null ? editor.logicalPositionToOffset(blockStart) : 0;
int selEnd = hasSelection && blockEnd != null ? editor.logicalPositionToOffset(blockEnd) : 0;
if (caretModel.supportsMultipleCarets()) {
hasSelection = true;
List<Caret> allCarets = caretModel.getAllCarets();
Caret fromCaret = allCarets.get(0);
Caret toCaret = allCarets.get(allCarets.size() - 1);
if (fromCaret == caretModel.getPrimaryCaret()) {
Caret tmp = fromCaret;
fromCaret = toCaret;
toCaret = tmp;
}
selStart = fromCaret.getLeadSelectionOffset();
selEnd = toCaret.getSelectionStart() == toCaret.getLeadSelectionOffset() ? toCaret.getSelectionEnd() : toCaret.getSelectionStart();
}
editor.setColumnMode(false);
caretModel.removeSecondaryCarets();
if (hasSelection) {
selectionModel.setSelection(selStart, selEnd);
}
@@ -271,7 +271,7 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
@Override
@NotNull
public Collection<Caret> getAllCarets() {
public List<Caret> getAllCarets() {
List<Caret> carets;
synchronized (myCarets) {
carets = new ArrayList<Caret>(myCarets);
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -154,8 +153,8 @@ public class TextComponentCaretModel implements CaretModel {
@NotNull
@Override
public Collection<Caret> getAllCarets() {
return Collections.singleton(myCaret);
public List<Caret> getAllCarets() {
return Collections.singletonList(myCaret);
}
@Nullable
@@ -0,0 +1,112 @@
/*
* 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.
*/
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
public class ToggleColumnModeActionMultiCaretTest extends LightPlatformCodeInsightFixtureTestCase {
public void setUp() throws Exception {
super.setUp();
EditorTestUtil.enableMultipleCarets();
}
public void tearDown() throws Exception {
EditorTestUtil.disableMultipleCarets();
super.tearDown();
}
public void testSingleCaretWithoutSelection() throws Exception {
doTestToggleOnOff("line1\n" +
"line<caret>2",
"line1\n" +
"line<caret>2",
"line1\n" +
"line<caret>2"
);
}
public void testSingleCaretWithForwardSelection() throws Exception {
doTestToggleOnOff("l<selection>ine1\n" +
"line<caret></selection>2",
"l<selection>ine<caret></selection>1\n" +
"l<selection>ine<caret></selection>2",
"l<selection>ine1\n" +
"line<caret></selection>2"
);
}
public void testSingleCaretWithBackwardSelection() throws Exception {
doTestToggleOnOff("l<selection><caret>ine1\n" +
"line</selection>2",
"l<selection><caret>ine</selection>1\n" +
"l<selection><caret>ine</selection>2",
"l<selection><caret>ine1\n" +
"line</selection>2"
);
}
public void testSingleCaretWithCrossSelection() throws Exception {
doTestToggleOnOff("line<selection><caret>1\n" +
"l</selection>ine2",
"l<selection>ine<caret></selection>1\n" +
"l<selection>ine<caret></selection>2",
"line<selection><caret>1\n" +
"l</selection>ine2"
);
}
public void testSingleCaretWithCrossSelection2() throws Exception {
doTestToggleOnOff("line<selection>1\n" +
"l<caret></selection>ine2",
"l<selection><caret>ine</selection>1\n" +
"l<selection><caret>ine</selection>2",
"line<selection>1\n" +
"l<caret></selection>ine2"
);
}
public void testMultipleCarets() throws Exception {
doTestToggleOnOff("<caret>l<selection>ine1\n" +
"line<caret></selection>2",
"<caret>l<selection>ine1\n" +
"line<caret></selection>2",
"<selection>line1\n" +
"line<caret></selection>2"
);
}
private void doTestToggleOnOff(String initialState, String afterToggleOn, String afterToggleOff) {
myFixture.configureByText(FileTypes.PLAIN_TEXT, initialState);
myFixture.performEditorAction("EditorToggleColumnMode");
myFixture.checkResult(afterToggleOn);
myFixture.performEditorAction("EditorToggleColumnMode");
myFixture.checkResult(afterToggleOff);
}
}