/** * Return the operation history to be used for managing undoable operations. * * @return the operation history to be used for executing, undoing, and * redoing operations. */ public static IOperationHistory getOperationHistory() { if (operationHistory == null) { operationHistory = new DefaultOperationHistory(); } return operationHistory; }
@Override public IStatus redo(IUndoContext context, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { Assert.isNotNull(context); IUndoableOperation operation = getRedoOperation(context); // info if there is no operation if (operation == null) { return IOperationHistory.NOTHING_TO_REDO_STATUS; } // error if operation is invalid if (!operation.canRedo()) { if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", "Redo operation not valid - " + operation); //$NON-NLS-1$//$NON-NLS-2$ } return IOperationHistory.OPERATION_INVALID_STATUS; } return doRedo(monitor, info, operation); }
@Override public IStatus undo(IUndoContext context, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { Assert.isNotNull(context); IUndoableOperation operation = getUndoOperation(context); // info if there is no operation if (operation == null) { return IOperationHistory.NOTHING_TO_UNDO_STATUS; } // error if operation is invalid if (!operation.canUndo()) { if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", "Undo operation not valid - " + operation); //$NON-NLS-1$ //$NON-NLS-2$ } return IOperationHistory.OPERATION_INVALID_STATUS; } return doUndo(monitor, info, operation); }
@Override public void dispose(IUndoContext context, boolean flushUndo, boolean flushRedo, boolean flushContext) { // dispose of any limit that was set for the context if it is not to be // used again. if (flushContext) { if (DEBUG_OPERATION_HISTORY_DISPOSE) { Tracing.printTrace("OPERATIONHISTORY", "Flushing context " + context); //$NON-NLS-1$//$NON-NLS-2$ } flushUndo(context); flushRedo(context); limits.remove(context); return; } if (flushUndo) { flushUndo(context); } if (flushRedo) { flushRedo(context); } }
@Override public void setLimit(IUndoContext context, int limit) { Assert.isTrue(limit >= 0); /* * The limit checking methods interpret a null context as a global limit * to be enforced. We do not wish to support a global limit in this * implementation, so we throw an exception for a null context. The rest * of the implementation can handle a null context, so subclasses can * override this if a global limit is desired. */ Assert.isNotNull(context); limits.put(context, Integer.valueOf(limit)); synchronized (undoRedoHistoryLock) { forceUndoLimit(context, limit); forceRedoLimit(context, limit); } }
IStatus status = getUndoApproval(operation, info); if (status.isOK()) { notifyAboutToUndo(operation); try { status = operation.undo(monitor, info); status = Status.CANCEL_STATUS; } catch (ExecutionException e) { notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ synchronized (undoRedoHistoryLock) { undoList.remove(operation); if (checkRedoLimit(operation)) { redoList.add(operation); } else { notifyUndone(operation); } else { notifyNotOK(operation, status);
forceUndoLimit(context, getLimit(context)); internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]); forceRedoLimit(context, getLimit(context)); internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]);
throws ExecutionException { IStatus status = getRedoApproval(operation, info); if (status.isOK()) { notifyAboutToRedo(operation); try { status = operation.redo(monitor, info); status = Status.CANCEL_STATUS; } catch (ExecutionException e) { notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ synchronized (undoRedoHistoryLock) { redoList.remove(operation); if (checkUndoLimit(operation)) { undoList.add(operation); } else { notifyRedone(operation); } else { notifyNotOK(operation, status);
IStatus status = getExecuteApproval(operation, info); if (!status.isOK()) { notifyAboutToExecute(operation); status = Status.CANCEL_STATUS; } catch (ExecutionException e) { notifyNotOK(operation); throw e; } catch (Exception e) { notifyNotOK(operation); throw new ExecutionException( "While executing the operation, an exception occurred", e); //$NON-NLS-1$ notifyDone(operation); add(operation); } else { notifyNotOK(operation, status);
private void forceRedoLimit(IUndoContext context, int max) { synchronized (undoRedoHistoryLock) { Object[] filtered = filter(redoList, context); int size = filtered.length; if (size > 0) { int index = 0; while (size > max) { IUndoableOperation removed = (IUndoableOperation) filtered[index]; if (context == GLOBAL_UNDO_CONTEXT || removed.getContexts().length == 1) { /* * remove the operation if we are enforcing a global limit * or if the operation only has the specified context */ redoList.remove(removed); internalRemove(removed); } else { /* * if the operation has multiple contexts and we've reached * the limit for only one of them, then just remove the * context, not the operation. */ removed.removeContext(context); } size--; index++; } } } }
if (checkUndoLimit(operation)) { synchronized (undoRedoHistoryLock) { undoList.add(operation); notifyAdd(operation); flushRedo(contexts[i]);
if (operationOK) { if (mode == EXECUTE) { notifyDone(endedComposite); add(endedComposite); notifyNotOK(endedComposite);
Object[] filtered = filter(undoList, context); for (int i = 0; i < filtered.length; i++) { IUndoableOperation operation = (IUndoableOperation) filtered[i]; internalRemove(operation); } else { internalRemove(operation); notifyNotOK(endedComposite);
/** * Check the redo limit before adding an operation. In theory the redo limit * should never be reached, because the redo items are transferred from the * undo history, which has the same limit. The redo history is cleared * whenever a new operation is added. We check for completeness since * implementations may change over time. * * Return a boolean indicating whether the redo should proceed. */ private boolean checkRedoLimit(IUndoableOperation operation) { IUndoContext[] contexts = operation.getContexts(); for (IUndoContext context : contexts) { int limit = getLimit(context); if (limit > 0) { forceRedoLimit(context, limit - 1); } else { // this context has a 0 limit operation.removeContext(context); } } return operation.getContexts().length > 0; }
@Override public IUndoableOperation[] getRedoHistory(IUndoContext context) { Assert.isNotNull(context); return filter(redoList, context); }
@Override public IStatus redoOperation(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { Assert.isNotNull(operation); IStatus status; if (operation.canRedo()) { status = doRedo(monitor, info, operation); } else { if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", "Redo operation not valid - " + operation); //$NON-NLS-1$ //$NON-NLS-2$ } status = IOperationHistory.OPERATION_INVALID_STATUS; } return status; }
@Override public IStatus undoOperation(IUndoableOperation operation, IProgressMonitor monitor, IAdaptable info) throws ExecutionException { Assert.isNotNull(operation); IStatus status; if (operation.canUndo()) { status = doUndo(monitor, info, operation); } else { if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", "Undo operation not valid - " + operation); //$NON-NLS-1$//$NON-NLS-2$ } status = IOperationHistory.OPERATION_INVALID_STATUS; } return status; }
IStatus status = getUndoApproval(operation, info); if (status.isOK()) { notifyAboutToUndo(operation); try { status = operation.undo(monitor, info); status = Status.CANCEL_STATUS; } catch (ExecutionException e) { notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ synchronized (undoRedoHistoryLock) { undoList.remove(operation); if (checkRedoLimit(operation)) { redoList.add(operation); } else { notifyUndone(operation); } else { notifyNotOK(operation, status);
forceUndoLimit(context, getLimit(context)); internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]); forceRedoLimit(context, getLimit(context)); internalRemove(operation); for (int i = 0; i < replacements.length; i++) { notifyAdd(replacements[i]);
throws ExecutionException { IStatus status = getRedoApproval(operation, info); if (status.isOK()) { notifyAboutToRedo(operation); try { status = operation.redo(monitor, info); status = Status.CANCEL_STATUS; } catch (ExecutionException e) { notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ notifyNotOK(operation); if (DEBUG_OPERATION_HISTORY_UNEXPECTED) { Tracing.printTrace("OPERATIONHISTORY", //$NON-NLS-1$ synchronized (undoRedoHistoryLock) { redoList.remove(operation); if (checkUndoLimit(operation)) { undoList.add(operation); } else { notifyRedone(operation); } else { notifyNotOK(operation, status);