UnitResult Redo() { if (globallyRedoableUnits.Count < 1) { throw new InvalidOperationException("No unit to redo."); /* TODO: Make localizable resource. */ } var unit = globallyRedoableUnits.Pop(); var eventArgs = new CancellableUndoServiceEventArgs(unit); OnRedoing(eventArgs); if (eventArgs.Cancel) { globallyRedoableUnits.AddLast(unit); return(UnitResult.Cancelled); } var internalUnit = (IInternalUnit)unit; globallyRepeatableUnits.AddLast(internalUnit); globallyUndoableUnits.AddLast(unit); var result = internalUnit.PerformUnit(internalUnit.Argument, UnitMode.Redo); TrimIfRequired(); OnRedone(new UndoServiceEventArgs(unit)); return(result); }
UnitResult Undo() { if (globallyRepeatableUnits.Count < 1) { throw new InvalidOperationException("No unit to undo."); } IUndoableUnit undoableUnit = globallyUndoableUnits.Pop(); IInternalUnit repeatableUnit = globallyRepeatableUnits.Pop(); var eventArgs = new CancellableUndoServiceEventArgs(undoableUnit); OnUndoing(eventArgs); if (eventArgs.Cancel) { globallyUndoableUnits.AddLast(undoableUnit); globallyRepeatableUnits.AddLast(repeatableUnit); return(UnitResult.Cancelled); } globallyRedoableUnits.AddLast(undoableUnit); UnitResult result = undoableUnit.Undo(); OnUndone(new UndoServiceEventArgs(undoableUnit)); return(result); }
/// <summary> /// Undoes the execution of a previous <see cref="IUnit"/>. /// </summary> /// <exception cref="InvalidOperationException"> /// Occurs if there are no previously executed units to undo.</exception> public UnitResult Undo(object ownerKey) { if (ownerKey == null) { return(Undo()); } if (!undoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> undoableUnits)) { throw new InvalidOperationException("No undoable units for the specified owner key."); } IUndoableUnit undoableUnit = undoableUnits.Pop(); if (!repeatableDictionary.TryGetValue(ownerKey, out UnitCollection <IInternalUnit> repeatableUnits)) { throw new InvalidOperationException("No repeatable units for the specified owner key."); } repeatableUnits.RemoveLast(); var eventArgs = new CancellableUndoServiceEventArgs(undoableUnit) { OwnerKey = ownerKey }; OnUndoing(eventArgs); if (eventArgs.Cancel) { undoableUnits.AddLast(undoableUnit); return(UnitResult.Cancelled); } if (!redoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> redoableUnits)) { redoableUnits = new UnitCollection <IUndoableUnit>(); redoableDictionary[ownerKey] = redoableUnits; } redoableUnits.AddLast(undoableUnit); var result = undoableUnit.Undo(); TrimIfRequired(ownerKey); OnUndone(new UndoServiceEventArgs(undoableUnit)); return(result); }
/// <summary>Executes the specified unit.</summary> /// <param name="unit">The command to execute.</param> /// <param name="argument">The argument passed to the unit on execution.</param> /// <param name="ownerKey">An object identifying the owner of the unit.</param> public UnitResult PerformUnit <T>( UndoableUnitBase <T> unit, T argument, object ownerKey) { //AssertArg.IsNotNull(unit, nameof(unit)); if (unit == null) { throw new ArgumentNullException(nameof(unit)); } if (ownerKey == null) { return(PerformUnit(unit, argument)); } var eventArgs = new CancellableUndoServiceEventArgs(unit) { OwnerKey = ownerKey }; OnExecuting(eventArgs); if (eventArgs.Cancel) { return(UnitResult.Cancelled); } redoableDictionary.Remove(ownerKey); if (!repeatableDictionary.TryGetValue(ownerKey, out UnitCollection <IInternalUnit> repeatableUnits)) { repeatableUnits = new UnitCollection <IInternalUnit>(); repeatableDictionary[ownerKey] = repeatableUnits; } repeatableUnits.AddLast(unit); if (!undoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> undoableUnits)) { undoableUnits = new UnitCollection <IUndoableUnit>(); undoableDictionary[ownerKey] = undoableUnits; } undoableUnits.AddLast(unit); UnitResult result = unit.PerformUnit(argument, UnitMode.FirstTime); TrimIfRequired(ownerKey); OnExecuted(new UndoServiceEventArgs(unit)); return(result); }
/// <summary> /// Performs the execution of a <see cref="IUnit"/> /// instance that has been undone, then places it back /// into the command stack. /// </summary> public UnitResult Redo(object ownerKey) { if (ownerKey == null) { return(Redo()); } if (!redoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> redoableUnits)) { throw new InvalidOperationException("No units to be redone for the specified owner key."); } IUndoableUnit unit = redoableUnits.Pop(); var eventArgs = new CancellableUndoServiceEventArgs(unit); OnRedoing(eventArgs); if (eventArgs.Cancel) { redoableUnits.AddLast(unit); return(UnitResult.Cancelled); } var internalUnit = (IInternalUnit)unit; if (!repeatableDictionary.TryGetValue(ownerKey, out UnitCollection <IInternalUnit> repeatableUnits)) { repeatableUnits = new UnitCollection <IInternalUnit>(); } repeatableUnits.AddLast(internalUnit); if (!undoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> undoableUnits)) { undoableUnits = new UnitCollection <IUndoableUnit>(); } undoableUnits.AddLast(unit); UnitResult result = internalUnit.PerformUnit(internalUnit.Argument, UnitMode.Redo); TrimIfRequired(ownerKey); OnRedone(new UndoServiceEventArgs(unit)); return(result); }
UnitResult PerformUnit <T>(UndoableUnitBase <T> unit, T argument) { var eventArgs = new CancellableUndoServiceEventArgs(unit); OnExecuting(eventArgs); if (eventArgs.Cancel) { return(UnitResult.Cancelled); } globallyRedoableUnits.Clear(); globallyRepeatableUnits.AddLast(unit); globallyUndoableUnits.AddLast(unit); UnitResult result = unit.PerformUnit(argument, UnitMode.FirstTime); TrimIfRequired(); OnExecuted(new UndoServiceEventArgs(unit)); return(result); }
UnitResult Repeat() { var unit = globallyRepeatableUnits.Peek(); if (!unit.Repeatable) { return(UnitResult.NoUnit); } var eventArgs = new CancellableUndoServiceEventArgs(unit); OnExecuting(eventArgs); if (eventArgs.Cancel) { return(UnitResult.Cancelled); } globallyRedoableUnits.Clear(); globallyRepeatableUnits.AddLast(unit); var undoableUnit = unit as IUndoableUnit; if (undoableUnit != null) { globallyUndoableUnits.AddLast(undoableUnit); } else { globallyUndoableUnits.Clear(); globallyRedoableUnits.Clear(); } var result = unit.PerformUnit(unit.Argument, UnitMode.Repeat); OnExecuted(new UndoServiceEventArgs(unit)); return(result); }
void OnRedoing(CancellableUndoServiceEventArgs e) { redoing?.Invoke(this, e); }
void OnExecuting(CancellableUndoServiceEventArgs e) { executing?.Invoke(this, e); }
public UnitResult Repeat(object ownerKey) { if (ownerKey == null) { return(Repeat()); } if (!repeatableDictionary.TryGetValue(ownerKey, out UnitCollection <IInternalUnit> repeatableUnits)) { throw new InvalidOperationException( "No units to be redone for the specified owner key."); } var unit = repeatableUnits.Peek(); if (!unit.Repeatable) { return(UnitResult.NoUnit); } var eventArgs = new CancellableUndoServiceEventArgs(unit) { OwnerKey = ownerKey }; OnExecuting(eventArgs); if (eventArgs.Cancel) { return(UnitResult.Cancelled); } repeatableUnits.AddLast(unit); if (!undoableDictionary.TryGetValue(ownerKey, out UnitCollection <IUndoableUnit> undoableUnits)) { undoableUnits = new UnitCollection <IUndoableUnit>(); undoableDictionary[ownerKey] = undoableUnits; } var undoableUnit = unit as IUndoableUnit; if (undoableUnit != null) { undoableUnits.AddLast(undoableUnit); } else { /* It's not undoable so we clear the list of undoable units. * This is because this unit may cause the previous * undo activities to be rendered invalid. */ undoableDictionary[ownerKey] = null; redoableDictionary[ownerKey] = null; } UnitResult result = unit.PerformUnit(unit.Argument, UnitMode.Repeat); TrimIfRequired(ownerKey); OnExecuted(new UndoServiceEventArgs(unit)); return(result); }