undo: refactored actions

This commit is contained in:
Anton Makeev
2010-10-11 13:50:17 +04:00
parent edffc8f3c2
commit edd0e92c50
18 changed files with 253 additions and 188 deletions
@@ -23,9 +23,8 @@ import com.intellij.ide.projectView.impl.nodes.PackageElement;
import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.GlobalUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
@@ -169,7 +168,7 @@ public class PsiPackageImpl extends PsiElementBase implements PsiPackage, Querya
final String oldQualifedName = myQualifiedName;
final boolean anyChanged = changePackagePrefixes(oldQualifedName, newQualifiedName);
if (anyChanged) {
UndoManager.getInstance(myManager.getProject()).undoableActionPerformed(new UndoableAction() {
UndoManager.getInstance(myManager.getProject()).undoableActionPerformed(new GlobalUndoableAction() {
public void undo() {
changePackagePrefixes(newQualifiedName, oldQualifedName);
}
@@ -177,14 +176,6 @@ public class PsiPackageImpl extends PsiElementBase implements PsiPackage, Querya
public void redo() {
changePackagePrefixes(oldQualifedName, newQualifiedName);
}
public DocumentReference[] getAffectedDocuments() {
return DocumentReference.EMPTY_ARRAY;
}
public boolean isGlobal() {
return true;
}
});
}
}
@@ -16,10 +16,8 @@
package com.intellij.psi.impl.source;
import com.intellij.lang.Language;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceManager;
import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -237,24 +235,19 @@ public class PsiCodeFragmentImpl extends PsiFileImpl implements JavaCodeFragment
//}
}
private static class ImportClassUndoableAction implements UndoableAction {
private static class ImportClassUndoableAction extends BasicUndoableAction {
private final String myClassName;
private final String myQName;
private final LinkedHashMap<String, String> myPseudoImports;
private final DocumentReference[] myReferences;
public ImportClassUndoableAction(final String className,
final String qName,
final Document document,
final LinkedHashMap<String, String> pseudoImportsMap) {
super(document);
myClassName = className;
myQName = qName;
myPseudoImports = pseudoImportsMap;
myReferences = new DocumentReference[]{DocumentReferenceManager.getInstance().create(document)};
}
public boolean isGlobal() {
return false;
}
public void undo() {
@@ -264,10 +257,6 @@ public class PsiCodeFragmentImpl extends PsiFileImpl implements JavaCodeFragment
public void redo() {
myPseudoImports.put(myClassName, myQName);
}
public DocumentReference[] getAffectedDocuments() {
return myReferences;
}
}
public ExceptionHandler getExceptionHandler() {
@@ -140,8 +140,9 @@ public abstract class WriteCommandAction<T> extends BaseActionRunnable<T> {
// is put into undo queue
final RunResult[] results = {result};
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
if (isGlobalUndoAction()) CommandProcessor.getInstance().markCurrentCommandAsGlobal(myProject);
results[0].run();
results[0] = null;
}
@@ -19,12 +19,12 @@
*/
package com.intellij.openapi.command.undo;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class UndoUtil {
@@ -40,37 +40,13 @@ public class UndoUtil {
Project project = file.getProject();
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
if (document == null) return;
final DocumentReference ref = DocumentReferenceManager.getInstance().create(document);
markDocumentReferenceForUndo(project, ref, "markDocumentForUndo: " + file);
CommandProcessor.getInstance().addAffectedDocuments(project, document);
}
/**
* @deprecated please use CommandProcessor.getInstance().addAffectedFiles instead
*/
public static void markVirtualFileForUndo(@NotNull Project project, @NotNull VirtualFile file) {
final DocumentReference ref = DocumentReferenceManager.getInstance().create(file);
markDocumentReferenceForUndo(project, ref, "markVirtualFileForUndo: " + file.getPath());
}
private static void markDocumentReferenceForUndo(final Project project,
final DocumentReference ref,
@NonNls final String debugName) {
UndoManager.getInstance(project).undoableActionPerformed(new UndoableAction() {
public void undo() {
}
public void redo() {
}
public DocumentReference[] getAffectedDocuments() {
return new DocumentReference[]{ref};
}
public boolean isGlobal() {
return false;
}
@NonNls
public String toString() {
return debugName;
}
});
CommandProcessor.getInstance().addAffectedFiles(project, file);
}
}
@@ -29,10 +29,10 @@ import com.intellij.openapi.command.CommandAdapter;
import com.intellij.openapi.command.CommandEvent;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceManager;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentAdapter;
@@ -246,10 +246,9 @@ public class TemplateState implements Disposable {
myProcessor = processor;
final DocumentReference[] refs =
DocumentReference[] refs =
myDocument == null ? null : new DocumentReference[]{DocumentReferenceManager.getInstance().create(myDocument)};
UndoManager.getInstance(myProject).undoableActionPerformed(new UndoableAction() {
UndoManager.getInstance(myProject).undoableActionPerformed(new BasicUndoableAction(refs) {
public void undo() {
if (myDocument != null) {
fireTemplateCancelled();
@@ -264,14 +263,6 @@ public class TemplateState implements Disposable {
//TODO:
// throw new UnexpectedUndoException("Not implemented");
}
public DocumentReference[] getAffectedDocuments() {
return refs;
}
public boolean isGlobal() {
return false;
}
});
myTemplateIndented = false;
myCurrentVariableNumber = -1;
@@ -207,7 +207,7 @@ public class Browser extends JPanel {
else if (ref.startsWith("invoke:")) {
int actionNumber = Integer.parseInt(ref.substring("invoke:".length()));
getTool().getQuickFixes(new RefElement[]{(RefElement)myCurrentEntity})[actionNumber]
.doApplyFix(new RefElement[]{(RefElement)myCurrentEntity}, myView);
.doApplyFix(new RefElement[]{(RefElement)myCurrentEntity}, myView, null);
}
else if (ref.startsWith("invokelocal:")) {
int actionNumber = Integer.parseInt(ref.substring("invokelocal:".length()));
@@ -172,13 +172,12 @@ public class FileUndoProvider extends VirtualFileAdapter implements UndoProvider
return (UndoManagerImpl)UndoManager.getGlobalInstance();
}
private class MyUndoableAction implements UndoableAction {
private final DocumentReference[] myReferences;
private class MyUndoableAction extends GlobalUndoableAction {
private ChangeRange myActionChangeRange;
private ChangeRange myUndoChangeRange;
public MyUndoableAction(DocumentReference r) {
myReferences = new DocumentReference[]{r};
super(r);
myActionChangeRange = new ChangeRange(myGateway, myLocalHistory, myLastChange);
}
@@ -201,13 +200,5 @@ public class FileUndoProvider extends VirtualFileAdapter implements UndoProvider
throw new UnexpectedUndoException(e.getMessage());
}
}
public DocumentReference[] getAffectedDocuments() {
return myReferences;
}
public boolean isGlobal() {
return true;
}
}
}
@@ -19,7 +19,8 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nls;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class CommandProcessor {
@@ -30,26 +31,37 @@ public abstract class CommandProcessor {
/**
* @deprecated use {@link #executeCommand(com.intellij.openapi.project.Project, java.lang.Runnable, java.lang.String, java.lang.Object)}
*/
public abstract void executeCommand(Runnable runnable, @Nls String name, Object groupId);
public abstract void executeCommand(@NotNull Runnable runnable,
@Nullable String name,
@Nullable Object groupId);
public abstract void executeCommand(Project project, Runnable runnable, @Nls String name, Object groupId);
public abstract void executeCommand(@Nullable Project project,
@NotNull Runnable runnable,
@Nullable String name,
@Nullable Object groupId);
public abstract void executeCommand(Project project,
Runnable runnable,
@Nls String name,
Object groupId,
UndoConfirmationPolicy undoConfirmationPolicy);
public abstract void executeCommand(@Nullable Project project,
@NotNull Runnable runnable,
@Nullable String name,
@Nullable Object groupId,
@Nullable Document document);
public abstract void executeCommand(Project project,
Runnable command,
String name,
Object groupId,
UndoConfirmationPolicy undoConfirmationPolicy,
Document document);
public abstract void executeCommand(@Nullable Project project,
@NotNull Runnable runnable,
@Nullable String name,
@Nullable Object groupId,
@NotNull UndoConfirmationPolicy confirmationPolicy);
public abstract void setCurrentCommandName(@Nls String name);
public abstract void executeCommand(@Nullable Project project,
@NotNull Runnable command,
@Nullable String name,
@Nullable Object groupId,
@NotNull UndoConfirmationPolicy confirmationPolicy,
@Nullable Document document);
public abstract void setCurrentCommandGroupId(Object groupId);
public abstract void setCurrentCommandName(@Nullable String name);
public abstract void setCurrentCommandGroupId(@Nullable Object groupId);
@Nullable
public abstract Runnable getCurrentCommand();
@@ -63,15 +75,19 @@ public abstract class CommandProcessor {
@Nullable
public abstract Project getCurrentCommandProject();
public abstract void addCommandListener(CommandListener listener);
public abstract void addCommandListener(CommandListener listener, Disposable parentDisposable);
public abstract void removeCommandListener(CommandListener listener);
public abstract void runUndoTransparentAction(Runnable action);
public abstract void runUndoTransparentAction(@NotNull Runnable action);
public abstract boolean isUndoTransparentActionInProgress();
public abstract void markCurrentCommandAsGlobal(Project project);
public abstract void markCurrentCommandAsGlobal(@Nullable Project project);
public abstract void addAffectedDocuments(@Nullable Project project, @NotNull Document... docs);
public abstract void addAffectedFiles(@Nullable Project project, @NotNull VirtualFile... files);
public abstract void addCommandListener(@NotNull CommandListener listener);
public abstract void addCommandListener(@NotNull CommandListener listener, @NotNull Disposable parentDisposable);
public abstract void removeCommandListener(@NotNull CommandListener listener);
}
@@ -0,0 +1,56 @@
/*
* Copyright 2000-2010 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.command.undo;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class BasicUndoableAction implements UndoableAction {
private final DocumentReference[] myRefs;
public BasicUndoableAction() {
myRefs = null;
}
public BasicUndoableAction(@Nullable DocumentReference... refs) {
myRefs = refs;
}
public BasicUndoableAction(@NotNull Document... docs) {
myRefs = new DocumentReference[docs.length];
for (int i = 0; i < docs.length; i++) {
myRefs[i] = DocumentReferenceManager.getInstance().create(docs[i]);
}
}
public BasicUndoableAction(@NotNull VirtualFile... files) {
myRefs = new DocumentReference[files.length];
for (int i = 0; i < files.length; i++) {
myRefs[i] = DocumentReferenceManager.getInstance().create(files[i]);
}
}
public DocumentReference[] getAffectedDocuments() {
return myRefs;
}
public boolean isGlobal() {
return false;
}
}
@@ -16,15 +16,27 @@
package com.intellij.openapi.command.undo;
/**
* @author Dmitry Avdeev
*/
public abstract class NonDocumentUndoableAction implements UndoableAction {
public DocumentReference[] getAffectedDocuments() {
return null;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
public abstract class GlobalUndoableAction extends BasicUndoableAction {
public GlobalUndoableAction() {
}
public final boolean isGlobal() {
public GlobalUndoableAction(DocumentReference... refs) {
super(refs);
}
public GlobalUndoableAction(@NotNull Document... docs) {
super(docs);
}
public GlobalUndoableAction(@NotNull VirtualFile... files) {
super(files);
}
public boolean isGlobal() {
return true;
}
}
@@ -35,6 +35,6 @@ public interface UndoableAction {
/**
* Global actions are those, that can be undone not only from the document of the file, but also from the project tree view.
* */
*/
boolean isGlobal();
}
@@ -16,8 +16,10 @@
package com.intellij.openapi.command.impl;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.command.undo.UnexpectedUndoException;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
@@ -37,7 +39,8 @@ public class CommandMerger {
private String myCommandName = null;
private boolean myValid = true;
private List<UndoableAction> myCurrentActions = new ArrayList<UndoableAction>();
private Set<DocumentReference> myAffectedDocuments = new THashSet<DocumentReference>();
private Set<DocumentReference> myAllAffectedDocuments = new THashSet<DocumentReference>();
private Set<DocumentReference> myAdditionalAffectedDocuments = new THashSet<DocumentReference>();
private EditorAndState myStateBefore;
private EditorAndState myStateAfter;
private UndoConfirmationPolicy myUndoConfirmationPolicy = UndoConfirmationPolicy.DEFAULT;
@@ -59,7 +62,7 @@ public class CommandMerger {
myCurrentActions.add(action);
DocumentReference[] refs = action.getAffectedDocuments();
if (refs != null) {
Collections.addAll(myAffectedDocuments, refs);
Collections.addAll(myAllAffectedDocuments, refs);
}
myForcedGlobal |= action.isGlobal();
}
@@ -82,7 +85,7 @@ public class CommandMerger {
private boolean shouldMerge(Object groupId, CommandMerger nextCommandToMerge) {
if (isTransparent() || nextCommandToMerge.isTransparent()) {
return !hasActions() || !nextCommandToMerge.hasActions() || myAffectedDocuments.equals(nextCommandToMerge.myAffectedDocuments);
return !hasActions() || !nextCommandToMerge.hasActions() || myAllAffectedDocuments.equals(nextCommandToMerge.myAllAffectedDocuments);
}
return !myForcedGlobal && !nextCommandToMerge.myForcedGlobal && canMergeGroup(groupId, myLastGroupId);
}
@@ -94,11 +97,12 @@ public class CommandMerger {
private void merge(CommandMerger nextCommandToMerge) {
setBeforeState(nextCommandToMerge.myStateBefore);
myStateAfter = nextCommandToMerge.myStateAfter;
if(myTransparent) { // todo write test
if (myTransparent) { // todo write test
if (nextCommandToMerge.hasActions()) {
myTransparent &= nextCommandToMerge.myTransparent;
}
} else {
}
else {
if (!hasActions()) {
myTransparent = nextCommandToMerge.myTransparent;
}
@@ -106,7 +110,8 @@ public class CommandMerger {
myValid &= nextCommandToMerge.myValid;
myForcedGlobal |= nextCommandToMerge.myForcedGlobal;
myCurrentActions.addAll(nextCommandToMerge.myCurrentActions);
myAffectedDocuments.addAll(nextCommandToMerge.myAffectedDocuments);
myAllAffectedDocuments.addAll(nextCommandToMerge.myAllAffectedDocuments);
myAdditionalAffectedDocuments.addAll(nextCommandToMerge.myAdditionalAffectedDocuments);
mergeUndoConfirmationPolicy(nextCommandToMerge.getUndoConfirmationPolicy());
}
@@ -123,6 +128,19 @@ public class CommandMerger {
public void flushCurrentCommand() {
if (hasActions()) {
if (!myAdditionalAffectedDocuments.isEmpty()) {
DocumentReference[] refs = myAdditionalAffectedDocuments.toArray(new DocumentReference[myAdditionalAffectedDocuments.size()]);
myCurrentActions.add(new BasicUndoableAction(refs) {
@Override
public void undo() throws UnexpectedUndoException {
}
@Override
public void redo() throws UnexpectedUndoException {
}
});
}
myManager.getUndoStacksHolder().addToStacks(new UndoableGroup(myCommandName,
isGlobal(),
myManager.getProject(),
@@ -140,7 +158,8 @@ public class CommandMerger {
private void reset() {
myCurrentActions = new ArrayList<UndoableAction>();
myAffectedDocuments = new THashSet<DocumentReference>();
myAllAffectedDocuments = new THashSet<DocumentReference>();
myAdditionalAffectedDocuments = new THashSet<DocumentReference>();
myLastGroupId = null;
myForcedGlobal = false;
myTransparent = false;
@@ -152,7 +171,7 @@ public class CommandMerger {
}
private void clearRedoStacks(CommandMerger nextMerger) {
myManager.getRedoStacksHolder().clearStacks(isGlobal(), nextMerger.myAffectedDocuments);
myManager.getRedoStacksHolder().clearStacks(isGlobal(), nextMerger.myAllAffectedDocuments);
}
boolean isGlobal() {
@@ -169,7 +188,7 @@ public class CommandMerger {
private boolean affectsMultiplePhysicalDocs() {
int count = 0;
for (DocumentReference each : myAffectedDocuments) {
for (DocumentReference each : myAllAffectedDocuments) {
VirtualFile file = each.getFile();
if (file instanceof LightVirtualFile) continue;
if (++count > 1) return true;
@@ -211,13 +230,10 @@ public class CommandMerger {
return !myCurrentActions.isEmpty();
}
public Collection<DocumentReference> getAffectedDocuments() {
return myAffectedDocuments;
}
public boolean isUndoAvailable(Collection<DocumentReference> refs) {
if (hasNonUndoableActions()) return false;
if (refs.isEmpty()) return isGlobal() && hasActions();
for (DocumentReference each : refs) {
if (hasChangesOf(each)) return true;
}
@@ -236,7 +252,7 @@ public class CommandMerger {
DocumentReference[] refs = action.getAffectedDocuments();
if (refs == null || ArrayUtil.contains(ref, refs)) return true;
}
return false;
return hasActions() && myAdditionalAffectedDocuments.contains(ref);
}
public void setBeforeState(EditorAndState state) {
@@ -249,8 +265,13 @@ public class CommandMerger {
myStateAfter = state;
}
public void addAdditionalAffectedDocuments(Collection<DocumentReference> refs) {
myAllAffectedDocuments.addAll(refs);
myAdditionalAffectedDocuments.addAll(refs);
}
public void invalidateActionsFor(DocumentReference ref) {
if (myAffectedDocuments.contains(ref)) {
if (myAllAffectedDocuments.contains(ref)) {
myValid = false;
}
}
@@ -26,8 +26,10 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Stack;
@@ -69,27 +71,31 @@ public class CommandProcessorImpl extends CommandProcessorEx {
private int myUndoTransparentCount = 0;
public void executeCommand(Runnable runnable, String name, Object groupId) {
public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) {
executeCommand(null, runnable, name, groupId);
}
public void executeCommand(Project project, Runnable runnable, String name, Object groupId) {
public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) {
executeCommand(project, runnable, name, groupId, UndoConfirmationPolicy.DEFAULT);
}
public void executeCommand(Project project,
final Runnable command,
final String name,
final Object groupId,
UndoConfirmationPolicy undoConfirmationPolicy) {
executeCommand(project, command, name, groupId, undoConfirmationPolicy, null);
public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId, Document document) {
executeCommand(project, runnable, name, groupId, UndoConfirmationPolicy.DEFAULT, document);
}
public void executeCommand(Project project,
final Runnable command,
@NotNull final Runnable command,
final String name,
final Object groupId,
UndoConfirmationPolicy undoConfirmationPolicy,
@NotNull UndoConfirmationPolicy confirmationPolicy) {
executeCommand(project, command, name, groupId, confirmationPolicy, null);
}
public void executeCommand(Project project,
@NotNull final Runnable command,
final String name,
final Object groupId,
@NotNull UndoConfirmationPolicy confirmationPolicy,
Document document) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (project != null && project.isDisposed()) return;
@@ -104,7 +110,7 @@ public class CommandProcessorImpl extends CommandProcessorEx {
}
Throwable throwable = null;
try {
myCurrentCommand = new CommandDescriptor(command, project, name, groupId, undoConfirmationPolicy, document);
myCurrentCommand = new CommandDescriptor(command, project, name, groupId, confirmationPolicy, document);
fireCommandStarted();
command.run();
}
@@ -263,11 +269,11 @@ public class CommandProcessorImpl extends CommandProcessorEx {
return myCurrentCommand != null ? myCurrentCommand.myProject : null;
}
public void addCommandListener(CommandListener listener) {
public void addCommandListener(@NotNull CommandListener listener) {
myListeners.add(listener);
}
public void addCommandListener(final CommandListener listener, Disposable parentDisposable) {
public void addCommandListener(@NotNull final CommandListener listener, @NotNull Disposable parentDisposable) {
addCommandListener(listener);
Disposer.register(parentDisposable, new Disposable() {
public void dispose() {
@@ -276,11 +282,11 @@ public class CommandProcessorImpl extends CommandProcessorEx {
});
}
public void removeCommandListener(CommandListener listener) {
public void removeCommandListener(@NotNull CommandListener listener) {
myListeners.remove(listener);
}
public void runUndoTransparentAction(Runnable action) {
public void runUndoTransparentAction(@NotNull Runnable action) {
if (myUndoTransparentCount++ == 0) fireUndoTransparentStarted();
try {
action.run();
@@ -295,8 +301,21 @@ public class CommandProcessorImpl extends CommandProcessorEx {
}
public void markCurrentCommandAsGlobal(Project project) {
UndoManager manager = project != null ? UndoManager.getInstance(project) : UndoManager.getGlobalInstance();
((UndoManagerImpl)manager).markCurrentCommandAsGlobal();
getUndoManager(project).markCurrentCommandAsGlobal();
}
private UndoManagerImpl getUndoManager(Project project) {
return (UndoManagerImpl)(project != null ? UndoManager.getInstance(project) : UndoManager.getGlobalInstance());
}
@Override
public void addAffectedDocuments(Project project, @NotNull Document... docs) {
getUndoManager(project).addAffectedDocuments(docs);
}
@Override
public void addAffectedFiles(Project project, @NotNull VirtualFile... files) {
getUndoManager(project).addAffectedFiles(files);
}
private void fireCommandStarted() {
@@ -15,9 +15,7 @@
*/
package com.intellij.openapi.command.impl;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.DocumentReferenceManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
@@ -27,8 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NonNls;
class EditorChangeAction implements UndoableAction {
private final DocumentReference myReference;
class EditorChangeAction extends BasicUndoableAction {
private final int myOffset;
private final CharSequence myOldString;
private final CharSequence myNewString;
@@ -41,7 +38,7 @@ class EditorChangeAction implements UndoableAction {
CharSequence oldString,
CharSequence newString,
long oldTimeStamp) {
myReference = DocumentReferenceManager.getInstance().create(document);
super(document);
myOffset = offset;
myOldString = oldString == null ? "" : oldString;
@@ -83,7 +80,7 @@ class EditorChangeAction implements UndoableAction {
}
private void refreshFileStatus() {
VirtualFile f = myReference.getFile();
VirtualFile f = getAffectedDocuments()[0].getFile();
if (f == null || f instanceof LightVirtualFile) return;
for (Project each : ProjectManager.getInstance().getOpenProjects()) {
@@ -92,16 +89,9 @@ class EditorChangeAction implements UndoableAction {
}
}
public DocumentReference[] getAffectedDocuments() {
return new DocumentReference[]{myReference};
}
public boolean isGlobal() {
return false;
}
private DocumentEx getDocument() {
return (DocumentEx)myReference.getDocument();
return (DocumentEx)getAffectedDocuments()[0].getDocument();
}
@NonNls
@@ -20,7 +20,7 @@ import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.command.undo.UnexpectedUndoException;
import com.intellij.openapi.diagnostic.Logger;
public class NonUndoableAction implements UndoableAction {
class NonUndoableAction implements UndoableAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.command.undo.NonUndoableAction");
private final DocumentReference[] myRefs;
@@ -155,6 +155,7 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
public void commandStarted(CommandEvent event) {
onCommandStarted(event.getProject(), event.getUndoConfirmationPolicy());
if (event.getDocument() != null) addAffectedDocuments(event.getDocument());
}
public void commandFinished(CommandEvent event) {
@@ -257,10 +258,6 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
}
}
public void markCurrentCommandAsGlobal() {
myCurrentMerger.markAsGlobal();
}
@Override
public void nonundoableActionPerformed(final DocumentReference ref, final boolean isGlobal) {
ApplicationManager.getApplication().assertIsDispatchThread();
@@ -284,6 +281,34 @@ public class UndoManagerImpl extends UndoManager implements ProjectComponent, Ap
myCurrentMerger.addAction(action);
}
public void markCurrentCommandAsGlobal() {
myCurrentMerger.markAsGlobal();
}
public void addAffectedDocuments(Document... docs) {
if (!isInsideCommand()) {
LOG.error("Must be called inside command");
return;
}
List<DocumentReference> refs = new ArrayList<DocumentReference>(docs.length);
for (Document each : docs) {
refs.add(DocumentReferenceManager.getInstance().create(each));
}
myCurrentMerger.addAdditionalAffectedDocuments(refs);
}
public void addAffectedFiles(VirtualFile... files) {
if (!isInsideCommand()) {
LOG.error("Must be called inside command");
return;
}
List<DocumentReference> refs = new ArrayList<DocumentReference>(files.length);
for (VirtualFile each : files) {
refs.add(DocumentReferenceManager.getInstance().create(each));
}
myCurrentMerger.addAdditionalAffectedDocuments(refs);
}
public void invalidateActionsFor(DocumentReference ref) {
ApplicationManager.getApplication().assertIsDispatchThread();
myMerger.invalidateActionsFor(ref);
@@ -22,10 +22,13 @@ import com.intellij.ide.plugins.cl.PluginClassLoader;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.DocumentReference;
import com.intellij.openapi.command.undo.GlobalUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StorageScheme;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
@@ -59,7 +62,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Configuration that holds configured xml tag, attribute and method parameter
@@ -529,7 +531,7 @@ public final class Configuration implements PersistentStateComponent<Element>, M
public static <T> void replaceInjectionsWithUndo(final Project project, final T add, final T remove,
final List<? extends PsiElement> psiElementsToRemove,
final PairProcessor<T, T> actualProcessor) {
final UndoableAction action = new UndoableAction() {
final UndoableAction action = new GlobalUndoableAction() {
public void undo() {
actualProcessor.process(remove, add);
}
@@ -537,14 +539,6 @@ public final class Configuration implements PersistentStateComponent<Element>, M
public void redo() {
actualProcessor.process(add, remove);
}
public DocumentReference[] getAffectedDocuments() {
return DocumentReference.EMPTY_ARRAY;
}
public boolean isGlobal() {
return true;
}
};
final List<PsiFile> psiFiles = ContainerUtil.mapNotNull(psiElementsToRemove, new NullableFunction<PsiElement, PsiFile>() {
public PsiFile fun(final PsiElement psiAnnotation) {
@@ -17,7 +17,9 @@ package org.jetbrains.plugins.groovy.annotator.intentions.dynamic.ui;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.undo.*;
import com.intellij.openapi.command.undo.GlobalUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UnexpectedUndoException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentEvent;
@@ -330,12 +332,11 @@ public abstract class DynamicDialog extends DialogWrapper {
}
}
Document document = PsiDocumentManager.getInstance(myProject).getDocument(myContext.getContainingFile());
final DocumentReference[] refs = new DocumentReference[]{DocumentReferenceManager.getInstance().create(document)};
final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myContext.getContainingFile());
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
UndoManager.getInstance(myProject).undoableActionPerformed(new UndoableAction() {
UndoManager.getInstance(myProject).undoableActionPerformed(new GlobalUndoableAction(document) {
public void undo() throws UnexpectedUndoException {
final DItemElement itemElement;
@@ -368,14 +369,6 @@ public abstract class DynamicDialog extends DialogWrapper {
public void redo() throws UnexpectedUndoException {
addElement(mySettings);
}
public DocumentReference[] getAffectedDocuments() {
return refs;
}
public boolean isGlobal() {
return true;
}
});
addElement(mySettings);