Stop Move line up/down at the top/bottom correctly with multi-caret (IJ-CR-160892)

GitOrigin-RevId: adec4f82c09efaa52db71b94ebaa5ac9d89271c5
This commit is contained in:
Bas Leijdekkers
2025-05-13 17:43:07 +00:00
committed by intellij-monorepo-bot
parent 6e41b23672
commit faa72d6b42
@@ -7,6 +7,7 @@ import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -20,6 +21,7 @@ import java.util.List;
*/
@ApiStatus.Internal
public abstract class BaseMoveHandler extends EditorWriteActionHandler.ForEachCaret {
private static final Key<Key<?>> FIRST_CARET_VETO = new Key<>("FIRST_CARET_VETO");
protected final boolean isDown;
public BaseMoveHandler(boolean down) {
@@ -36,7 +38,14 @@ public abstract class BaseMoveHandler extends EditorWriteActionHandler.ForEachCa
final Document document = editor.getDocument();
int textLength = document.getTextLength();
List<Caret> adjusted = null;
for (Caret c : editor.getCaretModel().getAllCarets()) {
final List<Caret> carets = editor.getCaretModel().getAllCarets();
final Project project = editor.getProject();
assert project != null;
final PsiFile file = getPsiFile(project, editor);
final MoverWrapper mover = getSuitableMover(editor, file);
if (movementVetoed(caret, carets, mover == null)) return;
for (Caret c : carets) {
if (c != caret && c.getLogicalPosition().column == 0) {
if (adjusted == null) adjusted = new ArrayList<>();
int offset = c.getOffset();
@@ -45,11 +54,6 @@ public abstract class BaseMoveHandler extends EditorWriteActionHandler.ForEachCa
}
}
final Project project = editor.getProject();
assert project != null;
final PsiFile file = getPsiFile(project, editor);
final MoverWrapper mover = getSuitableMover(editor, file);
if (mover != null && mover.getInfo().toMove2 != null) {
LineRange range = mover.getInfo().toMove;
if ((range.startLine > 0 || isDown) && (range.endLine < document.getLineCount() || !isDown)) {
@@ -65,12 +69,30 @@ public abstract class BaseMoveHandler extends EditorWriteActionHandler.ForEachCa
}
}
private boolean movementVetoed(@NotNull Caret caret, List<Caret> carets, boolean blocked) {
Caret firstCaret = isDown ? carets.get(carets.size() - 1) : carets.get(0);
if (caret == firstCaret) {
if (blocked) {
firstCaret.putUserData(FIRST_CARET_VETO, FIRST_CARET_VETO);
return true;
}
}
else {
boolean vetoed = firstCaret.getUserData(FIRST_CARET_VETO) != null;
if (vetoed) {
Caret lastCaret = isDown ? carets.get(0) : carets.get(carets.size() - 1);
if (caret == lastCaret) firstCaret.putUserData(FIRST_CARET_VETO, null);
return true;
}
}
return false;
}
@Override
public boolean isEnabledForCaret(@NotNull Editor editor, @NotNull Caret caret, DataContext dataContext) {
if (editor.isViewer() || editor.isOneLineMode()) return false;
final Project project = editor.getProject();
if (project == null || project.isDisposed()) return false;
return true;
return project != null && !project.isDisposed();
}
protected abstract @Nullable PsiFile getPsiFile(@NotNull Project project, @NotNull Editor editor);