public boolean execute(boolean drop, boolean isInsideStartFinishGroup) {
    if (!myUndoableGroup.isUndoable()) {
      reportCannotUndo(
          CommonBundle.message("cannot.undo.error.contains.nonundoable.changes.message"),
          myUndoableGroup.getAffectedDocuments());
      return false;
    }

    Set<DocumentReference> clashing = getStackHolder().collectClashingActions(myUndoableGroup);
    if (!clashing.isEmpty()) {
      reportCannotUndo(
          CommonBundle.message("cannot.undo.error.other.affected.files.changed.message"), clashing);
      return false;
    }

    if (!isInsideStartFinishGroup && myUndoableGroup.shouldAskConfirmation(isRedo())) {
      if (!askUser()) return false;
    } else {
      if (restore(getBeforeState())) {
        setBeforeState(new EditorAndState(myEditor, myEditor.getState(FileEditorStateLevel.UNDO)));
        return true;
      }
    }

    Collection<VirtualFile> readOnlyFiles = collectReadOnlyAffectedFiles();
    if (!readOnlyFiles.isEmpty()) {
      final Project project = myManager.getProject();
      final VirtualFile[] files = VfsUtil.toVirtualFileArray(readOnlyFiles);

      if (project == null) {
        return false;
      }

      final ReadonlyStatusHandler.OperationStatus operationStatus =
          ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
      if (operationStatus.hasReadonlyFiles()) {
        return false;
      }
    }

    Collection<Document> readOnlyDocuments = collectReadOnlyDocuments();
    if (!readOnlyDocuments.isEmpty()) {
      for (Document document : readOnlyDocuments) {
        document.fireReadOnlyModificationAttempt();
      }
      return false;
    }

    getStackHolder().removeFromStacks(myUndoableGroup);
    if (!drop) {
      getReverseStackHolder().addToStacks(myUndoableGroup);
    }

    performAction();

    restore(getAfterState());

    return true;
  }
示例#2
0
  public void removeFromStacks(UndoableGroup group) {
    if (group.getAffectedDocuments().isEmpty()) return;

    if (group.isGlobal()) {
      assert myGlobalStack.getLast() == group;
      myGlobalStack.removeLast();
    }
    for (DocumentReference each : group.getAffectedDocuments()) {
      LinkedList<UndoableGroup> stack = getStack(each);
      assert stack.getLast() == group;
      stack.removeLast();
    }
  }
示例#3
0
  private void doAddToStack(LinkedList<UndoableGroup> stack, UndoableGroup group, int limit) {
    if (!group.isUndoable() && stack.isEmpty()) return;

    stack.addLast(group);
    while (stack.size() > limit) {
      stack.removeFirst();
    }
  }
  private boolean askUser() {
    String actionText = getActionName(myUndoableGroup.getCommandName());

    if (actionText.length() > 80) {
      actionText = actionText.substring(0, 80) + "... ";
    }

    return Messages.showOkCancelDialog(
            myManager.getProject(), actionText + "?", getActionName(), Messages.getQuestionIcon())
        == Messages.OK;
  }
 private Collection<VirtualFile> collectReadOnlyAffectedFiles() {
   Collection<DocumentReference> affectedDocument = myUndoableGroup.getAffectedDocuments();
   Collection<VirtualFile> readOnlyFiles = new ArrayList<VirtualFile>();
   for (DocumentReference documentReference : affectedDocument) {
     VirtualFile file = documentReference.getFile();
     if ((file != null) && file.isValid() && !file.isWritable()) {
       readOnlyFiles.add(file);
     }
   }
   return readOnlyFiles;
 }
 private Collection<Document> collectReadOnlyDocuments() {
   Collection<DocumentReference> affectedDocument = myUndoableGroup.getAffectedDocuments();
   Collection<Document> readOnlyDocs = new ArrayList<Document>();
   for (DocumentReference ref : affectedDocument) {
     if (ref instanceof DocumentReferenceByDocument) {
       Document doc = ref.getDocument();
       if (doc != null && !doc.isWritable()) readOnlyDocs.add(doc);
     }
   }
   return readOnlyDocs;
 }
示例#7
0
  @NotNull
  public UndoableGroup getLastAction(Collection<DocumentReference> refs) {
    if (refs.isEmpty()) return myGlobalStack.getLast();

    UndoableGroup mostRecentAction = null;
    int mostRecentDocTimestamp = myUndo ? -1 : Integer.MAX_VALUE;

    for (DocumentReference each : refs) {
      LinkedList<UndoableGroup> stack = getStack(each);
      // the stack for a document can be empty in case of compound editors with several documents
      if (stack.isEmpty()) continue;
      UndoableGroup lastAction = stack.getLast();

      int timestamp = lastAction.getCommandTimestamp();
      if (myUndo ? timestamp > mostRecentDocTimestamp : timestamp < mostRecentDocTimestamp) {
        mostRecentAction = lastAction;
        mostRecentDocTimestamp = timestamp;
      }
    }

    // result must not be null
    return mostRecentAction;
  }
示例#8
0
  public Set<DocumentReference> collectClashingActions(UndoableGroup group) {
    Set<DocumentReference> result = new THashSet<DocumentReference>();

    for (DocumentReference each : group.getAffectedDocuments()) {
      UndoableGroup last = getStack(each).getLast();
      if (last != group) {
        result.addAll(last.getAffectedDocuments());
      }
    }

    if (group.isGlobal()) {
      UndoableGroup last = myGlobalStack.getLast();
      if (last != group) {
        result.addAll(last.getAffectedDocuments());
      }
    }

    return result;
  }
示例#9
0
 public void collectAllAffectedDocuments(Collection<DocumentReference> result) {
   for (UndoableGroup each : myGlobalStack) {
     result.addAll(each.getAffectedDocuments());
   }
   collectLocalAffectedDocuments(result);
 }
示例#10
0
 private void doInvalidateAllGlobalActions(LinkedList<UndoableGroup> stack) {
   for (UndoableGroup g : stack) {
     g.invalidateIfGlobal();
   }
 }
示例#11
0
 public void addToStacks(UndoableGroup group) {
   if (group.isGlobal()) doAddToStack(myGlobalStack, group, UndoManagerImpl.GLOBAL_UNDO_LIMIT);
   for (DocumentReference each : group.getAffectedDocuments()) {
     doAddToStack(getStack(each), group, UndoManagerImpl.LOCAL_UNDO_LIMIT);
   }
 }
示例#12
0
 boolean isTransparent() {
   return myUndoableGroup.isTransparent();
 }