mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
undo should restore primary caret properly (IDEA-80056)
This commit is contained in:
@@ -224,9 +224,25 @@ public interface CaretModel {
|
||||
* If multiple carets are not supported, the behaviour is unspecified.
|
||||
*
|
||||
* @see #supportsMultipleCarets()
|
||||
* @see #getCaretsAndSelections()
|
||||
*/
|
||||
void setCaretsAndSelections(@NotNull List<CaretState> caretStates);
|
||||
|
||||
/**
|
||||
* Returns the current positions of all carets and their selections. The order of entries in the returned list does not necessarily
|
||||
* correspond to the order of {@link #getAllCarets()} method results. Passing the result of this method to
|
||||
* {@link #setCaretsAndSelections(java.util.List)} will restore the state of carets, including the internal caret order, in particular,
|
||||
* the caret, that was primary when this method was called, will be the primary one after corresponding
|
||||
* {@link #setCaretsAndSelections(java.util.List)} invocation.
|
||||
* <p>
|
||||
* If multiple carets are not supported, the behaviour is unspecified.
|
||||
*
|
||||
* @see #supportsMultipleCarets()
|
||||
* @see #setCaretsAndSelections(java.util.List)
|
||||
*/
|
||||
@NotNull
|
||||
List<CaretState> getCaretsAndSelections();
|
||||
|
||||
/**
|
||||
* Executes the given task for each existing caret. Carets are iterated in their position order. Set of carets to iterate over is
|
||||
* determined in the beginning and is not affected by the potential carets addition or removal by the task being executed.
|
||||
|
||||
@@ -221,6 +221,19 @@ public class CaretModelWindow implements CaretModel {
|
||||
myDelegate.setCaretsAndSelections(convertedStates);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CaretState> getCaretsAndSelections() {
|
||||
List<CaretState> caretsAndSelections = myDelegate.getCaretsAndSelections();
|
||||
List<CaretState> convertedStates = new ArrayList<CaretState>(caretsAndSelections.size());
|
||||
for (CaretState state : caretsAndSelections) {
|
||||
convertedStates.add(new CaretState(state.getCaretPosition() == null ? null : myEditorWindow.hostToInjected(state.getCaretPosition()),
|
||||
state.getSelectionStart() == null ? null : myEditorWindow.hostToInjected(state.getSelectionStart()),
|
||||
state.getSelectionEnd() == null ? null : myEditorWindow.hostToInjected(state.getSelectionEnd())));
|
||||
}
|
||||
return convertedStates;
|
||||
}
|
||||
|
||||
private InjectedCaret createInjectedCaret(Caret caret) {
|
||||
if (caret == null) {
|
||||
return null;
|
||||
|
||||
@@ -488,6 +488,20 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener,
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CaretState> getCaretsAndSelections() {
|
||||
synchronized (myCarets) {
|
||||
List<CaretState> states = new ArrayList<CaretState>(myCarets.size());
|
||||
for (CaretImpl caret : myCarets) {
|
||||
states.add(new CaretState(caret.getLogicalPosition(),
|
||||
myEditor.visualToLogicalPosition(caret.getSelectionStartPosition()),
|
||||
myEditor.visualToLogicalPosition(caret.getSelectionEndPosition())));
|
||||
}
|
||||
return states;
|
||||
}
|
||||
}
|
||||
|
||||
void fireCaretPositionChanged(CaretEvent caretEvent) {
|
||||
myCaretListeners.getMulticaster().caretPositionChanged(caretEvent);
|
||||
}
|
||||
|
||||
+6
@@ -187,6 +187,12 @@ public class TextComponentCaretModel implements CaretModel {
|
||||
throw new UnsupportedOperationException("Multiple carets are not supported");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CaretState> getCaretsAndSelections() {
|
||||
throw new UnsupportedOperationException("Multiple carets are not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runForEachCaret(@NotNull CaretAction action) {
|
||||
action.perform(myCaret);
|
||||
|
||||
+39
-15
@@ -29,7 +29,9 @@ import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.UserDataHolderBase;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.Navigatable;
|
||||
@@ -42,7 +44,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -226,19 +227,23 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware {
|
||||
protected TextEditorState getStateImpl(final Project project, @NotNull Editor editor, @NotNull FileEditorStateLevel level){
|
||||
TextEditorState state = new TextEditorState();
|
||||
CaretModel caretModel = editor.getCaretModel();
|
||||
Collection<Caret> allCarets = caretModel.getAllCarets();
|
||||
state.CARETS = new TextEditorState.CaretState[allCarets.size()];
|
||||
int i = 0;
|
||||
for (Caret caret : allCarets) {
|
||||
state.CARETS[i] = new TextEditorState.CaretState();
|
||||
state.CARETS[i].LINE = caret.getLogicalPosition().line;
|
||||
state.CARETS[i].COLUMN = caret.getLogicalPosition().column;
|
||||
LogicalPosition selectionStartPosition = editor.visualToLogicalPosition(caret.getSelectionStartPosition());
|
||||
LogicalPosition selectionEndPosition = editor.visualToLogicalPosition(caret.getSelectionEndPosition());
|
||||
state.CARETS[i].SELECTION_START_LINE = selectionStartPosition.line;
|
||||
state.CARETS[i].SELECTION_START_COLUMN = selectionStartPosition.column;
|
||||
state.CARETS[i].SELECTION_END_LINE = selectionEndPosition.line;
|
||||
state.CARETS[i++].SELECTION_END_COLUMN = selectionEndPosition.column;
|
||||
if (caretModel.supportsMultipleCarets()) {
|
||||
List<CaretState> caretsAndSelections = caretModel.getCaretsAndSelections();
|
||||
state.CARETS = new TextEditorState.CaretState[caretsAndSelections.size()];
|
||||
for (int i = 0; i < caretsAndSelections.size(); i++) {
|
||||
CaretState caretState = caretsAndSelections.get(i);
|
||||
LogicalPosition caretPosition = caretState.getCaretPosition();
|
||||
LogicalPosition selectionStartPosition = caretState.getSelectionStart();
|
||||
LogicalPosition selectionEndPosition = caretState.getSelectionEnd();
|
||||
state.CARETS[i] = createCaretState(caretPosition, selectionStartPosition, selectionEndPosition);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogicalPosition caretPosition = caretModel.getLogicalPosition();
|
||||
LogicalPosition selectionStartPosition = editor.offsetToLogicalPosition(editor.getSelectionModel().getSelectionStart());
|
||||
LogicalPosition selectionEndPosition = editor.offsetToLogicalPosition(editor.getSelectionModel().getSelectionEnd());
|
||||
state.CARETS = new TextEditorState.CaretState[1];
|
||||
state.CARETS[0] = createCaretState(caretPosition, selectionStartPosition, selectionEndPosition);
|
||||
}
|
||||
|
||||
// Saving scrolling proportion on UNDO may cause undesirable results of undo action fails to perform since
|
||||
@@ -253,6 +258,25 @@ public class TextEditorProvider implements FileEditorProvider, DumbAware {
|
||||
return state;
|
||||
}
|
||||
|
||||
private static TextEditorState.CaretState createCaretState(LogicalPosition caretPosition, LogicalPosition selectionStartPosition, LogicalPosition selectionEndPosition) {
|
||||
TextEditorState.CaretState caretState = new TextEditorState.CaretState();
|
||||
caretState.LINE = getLine(caretPosition);
|
||||
caretState.COLUMN = getColumn(caretPosition);
|
||||
caretState.SELECTION_START_LINE = getLine(selectionStartPosition);
|
||||
caretState.SELECTION_START_COLUMN = getColumn(selectionStartPosition);
|
||||
caretState.SELECTION_END_LINE = getLine(selectionEndPosition);
|
||||
caretState.SELECTION_END_COLUMN = getColumn(selectionEndPosition);
|
||||
return caretState;
|
||||
}
|
||||
|
||||
private static int getLine(@Nullable LogicalPosition pos) {
|
||||
return pos == null ? 0 : pos.line;
|
||||
}
|
||||
|
||||
private static int getColumn(@Nullable LogicalPosition pos) {
|
||||
return pos == null ? 0 : pos.column;
|
||||
}
|
||||
|
||||
protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
|
||||
if (editor.getCaretModel().supportsMultipleCarets()) {
|
||||
CaretModel caretModel = editor.getCaretModel();
|
||||
|
||||
+9
@@ -97,6 +97,15 @@ public class EditorMultiCaretUndoRedoTest extends AbstractEditorTest {
|
||||
verifyCaretsAndSelections(0, 2, 0, 0, 0, 2);
|
||||
}
|
||||
|
||||
public void testPrimaryCaretPositionAfterUndo() throws Exception {
|
||||
init("line1\n" +
|
||||
"line2");
|
||||
mouse().alt().clickAt(1, 1).dragTo(0, 0).release();
|
||||
type(' ');
|
||||
undo();
|
||||
assertEquals(new LogicalPosition(0, 0), myEditor.getCaretModel().getPrimaryCaret().getLogicalPosition());
|
||||
}
|
||||
|
||||
private void checkResult(final String text) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user