示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        /// <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);
        }
示例#4
0
        /// <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);
        }
示例#5
0
        /// <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);
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#8
0
 void OnRedoing(CancellableUndoServiceEventArgs e)
 {
     redoing?.Invoke(this, e);
 }
示例#9
0
 void OnExecuting(CancellableUndoServiceEventArgs e)
 {
     executing?.Invoke(this, e);
 }
示例#10
0
        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);
        }