package org.plantuml.idea.intentions; import com.intellij.codeInsight.intention.impl.BaseIntentionAction; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.BuildNumber; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.plantuml.idea.lang.PlantUmlFileType; public class ReverseArrowIntention extends BaseIntentionAction { public static final Logger logger = Logger.getInstance(ReverseArrowIntention.class); protected boolean supportsMultiCaret; public ReverseArrowIntention() { BuildNumber build = ApplicationInfoEx.getInstanceEx().getBuild(); //from 13.1 (135.475) supportsMultiCaret = build.getBaselineVersion() >= 135 && build.getBuildNumber() >= 475; } @NotNull @Override public String getFamilyName() { return "Reverse arrow"; } @NotNull @Override public String getText() { return getFamilyName(); } @Override public boolean isAvailable(@NotNull Project project, final Editor editor, PsiFile file) { if (!file.getFileType().equals(PlantUmlFileType.PLANTUML_FILE_TYPE)) return false; if (supportsMultiCaret) { boolean available = false; for (Caret caret : editor.getCaretModel().getAllCarets()) { if (caret.isValid()) { available = new ReverseArrowCommand(editor, caret.getOffset()).isAvailable(); if (available) { break; } } } return available; } else { return new ReverseArrowCommand(editor, editor.getCaretModel().getOffset()).isAvailable(); } } @Override public void invoke(@NotNull Project project, final Editor editor, PsiFile psiFile) throws IncorrectOperationException { if (supportsMultiCaret) { for (Caret caret : editor.getCaretModel().getAllCarets()) { if (caret.isValid()) { new ReverseArrowCommand(editor, caret.getOffset()).invoke(); } } } else { new ReverseArrowCommand(editor, editor.getCaretModel().getOffset()).invoke(); } } private class ReverseArrowCommand { private Editor editor; protected int caretOffset; public ReverseArrowCommand(Editor editor, int caretOffset) { this.editor = editor; this.caretOffset = caretOffset; } public boolean isAvailable() { return invoke(true); } public boolean invoke() { return invoke(false); } private boolean invoke(boolean validateOnly) { Document document = editor.getDocument(); int lineNumber = document.getLineNumber(caretOffset); int lineStartOffset = document.getLineStartOffset(lineNumber); int lineEndOffset = document.getLineEndOffset(lineNumber); String line = document.getText(TextRange.create(lineStartOffset, lineEndOffset)); int caretOffsetWithinLine = caretOffset - lineStartOffset; char[] chars = line.toCharArray(); Arrow arrow = Arrow.from(caretOffsetWithinLine, chars); int start = arrow.getStart(); int end = arrow.getEnd(); if (!validateOnly && arrow.isValid()) { char[] reverse = ArrowUtils.cutArrowAndReverse(chars, start, end); document.replaceString(lineStartOffset + start, lineStartOffset + end + 1, new String(reverse)); } return arrow.isValid(); } } }