mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ChangeModifierIntention: prevent flicker for fields and classes (unfortunately not for methods yet)
+ some other cosmetic changes (IDEA-CR-48063) GitOrigin-RevId: 9631635dd51c691555b668e4ff790ed273d815fb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4018b8bad1
commit
0186a7142b
+91
-49
@@ -21,8 +21,11 @@ import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.JBPopupListener;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -152,28 +155,25 @@ public class ChangeModifierIntention extends BaseElementAtCaretIntentionAction {
|
||||
}
|
||||
range = TextRange.from(pos, 0);
|
||||
}
|
||||
editor.getCaretModel().moveToOffset(range.getStartOffset());
|
||||
StartMarkAction markAction;
|
||||
try {
|
||||
markAction = StartMarkAction.start(editor, project, getFamilyName());
|
||||
}
|
||||
catch (StartMarkAction.AlreadyStartedException e) {
|
||||
Messages.showErrorDialog(project, e.getMessage(), StringUtil.toTitleCase(getFamilyName()));
|
||||
return;
|
||||
}
|
||||
|
||||
TextAttributes lvAttr = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(EditorColors.LIVE_TEMPLATE_ATTRIBUTES);
|
||||
RangeHighlighter highlighter = editor.getMarkupModel()
|
||||
.addRangeHighlighter(range.getStartOffset(), range.getEndOffset(), HighlighterLayer.LAST + 1, lvAttr,
|
||||
HighlighterTargetArea.EXACT_RANGE);
|
||||
highlighter.setGreedyToRight(true);
|
||||
highlighter.setGreedyToLeft(true);
|
||||
boolean extendLeft = range.getStartOffset() > 0 && !StringUtil.isWhiteSpace(sequence.charAt(range.getStartOffset() - 1));
|
||||
boolean extendRight = range.getEndOffset() < sequence.length() && !StringUtil.isWhiteSpace(sequence.charAt(range.getEndOffset()));
|
||||
String originalText = sequence.subSequence(range.getStartOffset(), range.getEndOffset()).toString();
|
||||
ModifierUpdater updater = new ModifierUpdater(file, document, range, getFamilyName());
|
||||
AccessModifier current = ContainerUtil.find(modifiers, m -> m.hasModifier(member));
|
||||
RangeMarker marker = document.createRangeMarker(range);
|
||||
marker.setGreedyToRight(true);
|
||||
marker.setGreedyToLeft(true);
|
||||
editor.getCaretModel().moveToOffset(range.getStartOffset());
|
||||
SmartPsiElementPointer<PsiMember> memberPointer = SmartPointerManager.createPointer(member);
|
||||
StartMarkAction markAction;
|
||||
try {
|
||||
markAction = StartMarkAction.start(editor, project, getFamilyName());
|
||||
}
|
||||
catch (StartMarkAction.AlreadyStartedException e) {
|
||||
return;
|
||||
}
|
||||
JBPopup popup = JBPopupFactory.getInstance().createPopupChooserBuilder(modifiers)
|
||||
.setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
|
||||
.setSelectedValue(current, true)
|
||||
@@ -182,52 +182,94 @@ public class ChangeModifierIntention extends BaseElementAtCaretIntentionAction {
|
||||
.setResizable(false)
|
||||
.setRequestFocus(true)
|
||||
.setFont(editor.getColorsScheme().getFont(EditorFontType.PLAIN))
|
||||
.setItemSelectedCallback(t -> {
|
||||
if (t == null) return;
|
||||
String updatedText;
|
||||
if (t == AccessModifier.PACKAGE_LOCAL) {
|
||||
updatedText = " ";
|
||||
.setItemSelectedCallback(updater::setModifier)
|
||||
.addListener(new JBPopupListener() {
|
||||
@Override
|
||||
public void onClosed(@NotNull LightweightWindowEvent event) {
|
||||
highlighter.dispose();
|
||||
if (!event.isOk()) {
|
||||
FinishMarkAction.finish(project, editor, markAction);
|
||||
updater.undoChange(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
updatedText = extendLeft ? extendRight ? " " + t + " " : " " + t
|
||||
: extendRight ? t + " " : t.toString();
|
||||
}
|
||||
WriteCommandAction.writeCommandAction(project, file)
|
||||
.withName(getFamilyName())
|
||||
.run(() -> document.replaceString(marker.getStartOffset(), marker.getEndOffset(), updatedText));
|
||||
})
|
||||
.setCancelCallback(() -> {
|
||||
highlighter.dispose();
|
||||
FinishMarkAction.finish(project, editor, markAction);
|
||||
undoChange(project, file, document, originalText, marker);
|
||||
return true;
|
||||
})
|
||||
.setItemChosenCallback(t -> {
|
||||
updater.undoChange(false);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
updater.setModifier(t);
|
||||
// do not commit document now: checkForConflicts should have original content
|
||||
// while the editor should display the updated content to prevent flicker
|
||||
PsiMember m = memberPointer.getElement();
|
||||
if (m != null) {
|
||||
setModifier(m, t);
|
||||
if (m == null) return;
|
||||
PsiModifierList modifierList = m.getModifierList();
|
||||
if (modifierList == null) return;
|
||||
final MultiMap<PsiElement, String> conflicts = checkForConflicts(m, t);
|
||||
if (conflicts == null ||
|
||||
!conflicts.isEmpty() && !new ConflictsDialog(project, conflicts, () -> changeModifier(modifierList, t)).showAndGet()) {
|
||||
//canceled by user
|
||||
FinishMarkAction.finish(project, editor, markAction);
|
||||
updater.undoChange(true);
|
||||
return;
|
||||
}
|
||||
updater.undoChange(false);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
changeModifier(modifierList, t);
|
||||
FinishMarkAction.finish(project, editor, markAction);
|
||||
})
|
||||
.createPopup();
|
||||
popup.showInBestPositionFor(editor);
|
||||
}
|
||||
|
||||
private void undoChange(@NotNull Project project,
|
||||
PsiFile file,
|
||||
Document document,
|
||||
String originalText,
|
||||
RangeMarker marker) {
|
||||
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
|
||||
FileEditor fileEditor = fileEditorManager.getSelectedEditor(file.getVirtualFile());
|
||||
UndoManager manager = UndoManager.getInstance(project);
|
||||
if (manager.isUndoAvailable(fileEditor)) {
|
||||
manager.undo(fileEditor);
|
||||
} else {
|
||||
WriteCommandAction.writeCommandAction(project, file)
|
||||
.withName(getFamilyName())
|
||||
.run(() -> document.replaceString(marker.getStartOffset(), marker.getEndOffset(), originalText));
|
||||
private static class ModifierUpdater {
|
||||
private final Document myDocument;
|
||||
private final boolean myExtendLeft, myExtendRight;
|
||||
private final String myOriginalText;
|
||||
private final RangeMarker myMarker;
|
||||
private final String myActionName;
|
||||
private final PsiFile myFile;
|
||||
|
||||
ModifierUpdater(@NotNull PsiFile file, @NotNull Document document, @NotNull TextRange range, @NotNull String actionName) {
|
||||
myDocument = document;
|
||||
myFile = file;
|
||||
myActionName = actionName;
|
||||
CharSequence sequence = document.getCharsSequence();
|
||||
myExtendLeft = range.getStartOffset() > 0 && !StringUtil.isWhiteSpace(sequence.charAt(range.getStartOffset() - 1));
|
||||
myExtendRight = range.getEndOffset() < sequence.length() && !StringUtil.isWhiteSpace(sequence.charAt(range.getEndOffset()));
|
||||
myOriginalText = sequence.subSequence(range.getStartOffset(), range.getEndOffset()).toString();
|
||||
myMarker = document.createRangeMarker(range);
|
||||
myMarker.setGreedyToRight(true);
|
||||
myMarker.setGreedyToLeft(true);
|
||||
}
|
||||
|
||||
void undoChange(boolean viaUndoManager) {
|
||||
Project project = myFile.getProject();
|
||||
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
|
||||
FileEditor fileEditor = fileEditorManager.getSelectedEditor(myFile.getVirtualFile());
|
||||
UndoManager manager = UndoManager.getInstance(project);
|
||||
if (viaUndoManager && manager.isUndoAvailable(fileEditor)) {
|
||||
manager.undo(fileEditor);
|
||||
}
|
||||
else {
|
||||
WriteCommandAction.writeCommandAction(project, myFile)
|
||||
.withName(myActionName)
|
||||
.run(() -> myDocument.replaceString(myMarker.getStartOffset(), myMarker.getEndOffset(), myOriginalText));
|
||||
}
|
||||
}
|
||||
|
||||
void setModifier(@Nullable AccessModifier target) {
|
||||
if (target == null) return;
|
||||
String updatedText;
|
||||
if (target == AccessModifier.PACKAGE_LOCAL) {
|
||||
updatedText = " ";
|
||||
}
|
||||
else {
|
||||
updatedText = myExtendLeft ? myExtendRight ? " " + target + " " : " " + target
|
||||
: myExtendRight ? target + " " : target.toString();
|
||||
}
|
||||
WriteCommandAction.writeCommandAction(myFile.getProject(), myFile)
|
||||
.withName(myActionName)
|
||||
.run(() -> myDocument.replaceString(myMarker.getStartOffset(), myMarker.getEndOffset(), updatedText));
|
||||
}
|
||||
PsiDocumentManager.getInstance(project).commitDocument(document);
|
||||
}
|
||||
|
||||
private static TextRange getRange(PsiMember member) {
|
||||
|
||||
Reference in New Issue
Block a user