@Override public void add(IUndoableOperation operation) { Assert.isNotNull(operation); /* * If we are in the middle of executing an open batching operation, and * this is not that operation, then we need only add the context of the * new operation to the batch. The operation itself is disposed since we * will never undo or redo it. We consider it to be triggered by the * batching operation and assume that its undo will be triggered by the * batching operation undo. */ synchronized (openCompositeLock) { if (openComposite != null && openComposite != operation) { openComposite.add(operation); return; } } if (checkUndoLimit(operation)) { synchronized (undoRedoHistoryLock) { undoList.add(operation); } notifyAdd(operation); // flush redo stack for related contexts IUndoContext[] contexts = operation.getContexts(); for (int i = 0; i < contexts.length; i++) { flushRedo(contexts[i]); } } else { // Dispose the operation since we will not have a reference to it. operation.dispose(); } }
@Override public void replaceOperation(IUndoableOperation operation, IUndoableOperation[] replacements) { // check the undo history first. boolean inUndo = false; synchronized (undoRedoHistoryLock) { int index = undoList.indexOf(operation); if (index > -1) { inUndo = true; undoList.remove(operation); // notify listeners after the lock on undoList is released ArrayList<IUndoContext> allContexts = new ArrayList<>(replacements.length); for (int i = 0; i < replacements.length; i++) { IUndoContext[] opContexts = replacements[i].getContexts(); for (int j = 0; j < opContexts.length; j++) { allContexts.add(opContexts[j]); } undoList.add(index, replacements[i]); // notify listeners after the lock on the history is // released } // recheck all the limits. We do this at the end so the index // doesn't change during replacement for (int i = 0; i < allContexts.size(); i++) { IUndoContext context = allContexts.get(i); forceUndoLimit(context, getLimit(context)); } } } if (inUndo) { // notify listeners of operations added and removed internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]); } return; } // operation was not in the undo history. Check the redo history. synchronized (undoRedoHistoryLock) { int index = redoList.indexOf(operation); if (index == -1) { return; } ArrayList<IUndoContext> allContexts = new ArrayList<>(replacements.length); redoList.remove(operation); // notify listeners after we release the lock on redoList for (int i = 0; i < replacements.length; i++) { IUndoContext[] opContexts = replacements[i].getContexts(); for (int j = 0; j < opContexts.length; j++) { allContexts.add(opContexts[j]); } redoList.add(index, replacements[i]); // notify listeners after we release the lock on redoList } // recheck all the limits. We do this at the end so the index // doesn't change during replacement for (int i = 0; i < allContexts.size(); i++) { IUndoContext context = allContexts.get(i); forceRedoLimit(context, getLimit(context)); } } // send listener notifications after we release the lock on the history internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]); } }