コード例 #1
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
        /// <summary>
        /// Creates a new transaction, nests it in the previously current transaction, and marks it current.
        /// If there is a redo stack, it gets cleared.
        /// UNDONE: should the redo-clearing happen now or when the new transaction is committed?
        /// </summary>
        /// <param name="description">A string description for the transaction.</param>
        /// <returns></returns>
        public ITextUndoTransaction CreateTransaction(string description)
        {
            if (string.IsNullOrEmpty(description))
            {
                throw new ArgumentException("description", string.Format(CultureInfo.CurrentUICulture, "Strings.ArgumentCannotBeNull {0} {1}", "CreateTransaction", "description"));
            }

            // If there is a pending transaction that has already been completed, we should not be permitted
            // to open a new transaction, since it cannot later be added to its parent.
            if ((_currentTransaction != null) && (_currentTransaction.State != UndoTransactionState.Open))
            {
                throw new InvalidOperationException("Strings.CannotCreateTransactionWhenCurrentTransactionNotOpen");
            }

            // new transactions that are visible should clear the redo stack.
            if (_currentTransaction == null)
            {
                foreach (var textUndoTransaction in _redoStack)
                {
                    var redoTransaction = (UndoTransactionImpl)textUndoTransaction;
                    redoTransaction.Invalidate();
                }

                _redoStack.Clear();
            }

            UndoTransactionImpl newTransaction = new UndoTransactionImpl(this, _currentTransaction, description);

            _currentTransaction = newTransaction;

            return(_currentTransaction);
        }
コード例 #2
0
        public UndoTransactionImpl(ITextUndoHistory history, ITextUndoTransaction parent, string description) {
            if (history == null) {
                throw new ArgumentNullException(nameof(history));
            }

            if (string.IsNullOrEmpty(description)) {
                throw new ArgumentNullException(nameof(description));
            }

            _history = history as UndoHistoryImpl;

            if (_history == null) {
                throw new ArgumentException("Invalid history in registry");
            }

            _parent = parent as UndoTransactionImpl;

            if (_parent == null && parent != null) {
                throw new ArgumentException("Invalid parent in transaction");
            }

            Description = description;

            _state = UndoTransactionState.Open;
            _primitives = new List<ITextUndoPrimitive>();
            _mergePolicy = NullMergeUndoTransactionPolicy.Instance;
            IsReadOnly = true;
        }
コード例 #3
0
ファイル: UndoTransactionImpl.cs プロジェクト: zachwieja/RTVS
        public UndoTransactionImpl(ITextUndoHistory history, ITextUndoTransaction parent, string description)
        {
            if (history == null)
            {
                throw new ArgumentNullException(nameof(history));
            }

            if (string.IsNullOrEmpty(description))
            {
                throw new ArgumentNullException(nameof(description));
            }

            _history = history as UndoHistoryImpl;

            if (_history == null)
            {
                throw new ArgumentException("Invalid history in registry");
            }

            _parent = parent as UndoTransactionImpl;

            if (_parent == null && parent != null)
            {
                throw new ArgumentException("Invalid parent in transaction");
            }

            Description = description;

            _state       = UndoTransactionState.Open;
            _primitives  = new List <ITextUndoPrimitive>();
            _mergePolicy = NullMergeUndoTransactionPolicy.Instance;
            IsReadOnly   = true;
        }
コード例 #4
0
 /// <summary>
 /// Copies all of the primitives from the given transaction, and appends them to the UndoPrimitives list.
 /// </summary>
 /// <param name="transaction">The UndoTransactionImpl to copy from.</param>
 public void CopyPrimitivesFrom(UndoTransactionImpl transaction)
 {
     foreach (var p in transaction.UndoPrimitives)
     {
         AddUndo(p);
     }
 }
コード例 #5
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
        /// <summary>
        /// This does two different things, depending on the MergeUndoTransactionPolicys in question.
        /// It either simply pushes the current transaction to the undo stack, OR it merges it with
        /// the most recent item in the stack.
        /// </summary>
        private void MergeOrPushToUndoStack(UndoTransactionImpl transaction)
        {
            ITextUndoTransaction transactionAdded;
            TextUndoTransactionCompletionResult transactionResult;

            UndoTransactionImpl utPrevious = _undoStack.Count > 0 ? _undoStack.Peek() as UndoTransactionImpl : null;

            if (utPrevious != null && ProceedWithMerge(transaction, utPrevious))
            {
                // Temporarily make utPrevious non-read-only, during merge.
                utPrevious.IsReadOnly = false;
                try {
                    transaction.MergePolicy.PerformTransactionMerge(utPrevious, transaction);
                } finally {
                    utPrevious.IsReadOnly = true;
                }

                // utPrevious is already on the undo stack, so we don't need to add it; but report
                // it as the added transaction in the UndoTransactionCompleted event.
                transactionAdded  = utPrevious;
                transactionResult = TextUndoTransactionCompletionResult.TransactionMerged;
            }
            else
            {
                _undoStack.Push(transaction);

                transactionAdded  = transaction;
                transactionResult = TextUndoTransactionCompletionResult.TransactionAdded;
            }

            RaiseUndoTransactionCompleted(transactionAdded, transactionResult);
        }
コード例 #6
0
 public UndoHistoryImpl(UndoHistoryRegistryImpl undoHistoryRegistry) {
     _currentTransaction = null;
     UndoHistoryRegistry = undoHistoryRegistry;
     _undoStack = new Stack<ITextUndoTransaction>();
     _redoStack = new Stack<ITextUndoTransaction>();
     _activeUndoOperationPrimitive = null;
     _state = TextUndoHistoryState.Idle;
 }
コード例 #7
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
        private bool ProceedWithMerge(UndoTransactionImpl transaction1, UndoTransactionImpl transaction2)
        {
            UndoHistoryRegistryImpl registry = UndoHistoryRegistry;

            return(transaction1.MergePolicy != null &&
                   transaction2.MergePolicy != null &&
                   transaction1.MergePolicy.TestCompatiblePolicy(transaction2.MergePolicy) &&
                   transaction1.MergePolicy.CanMerge(transaction1, transaction2));
        }
コード例 #8
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
 public UndoHistoryImpl(UndoHistoryRegistryImpl undoHistoryRegistry)
 {
     _currentTransaction           = null;
     UndoHistoryRegistry           = undoHistoryRegistry;
     _undoStack                    = new Stack <ITextUndoTransaction>();
     _redoStack                    = new Stack <ITextUndoTransaction>();
     _activeUndoOperationPrimitive = null;
     _state = TextUndoHistoryState.Idle;
 }
コード例 #9
0
        public DelegatedUndoPrimitiveImpl(UndoHistoryImpl history, UndoTransactionImpl parent, UndoableOperationCurried operationCurried) {
            RedoOperations = new Stack<UndoableOperationCurried>();
            _undoOperations = new Stack<UndoableOperationCurried>();

            _parent = parent;
            _history = history;
            _state = DelegatedUndoPrimitiveState.Inactive;

            _undoOperations.Push(operationCurried);
        }
コード例 #10
0
        public DelegatedUndoPrimitiveImpl(UndoHistoryImpl history, UndoTransactionImpl parent, UndoableOperationCurried operationCurried)
        {
            RedoOperations  = new Stack <UndoableOperationCurried>();
            _undoOperations = new Stack <UndoableOperationCurried>();

            _parent  = parent;
            _history = history;
            _state   = DelegatedUndoPrimitiveState.Inactive;

            _undoOperations.Push(operationCurried);
        }
コード例 #11
0
        public UndoTransactionImpl(ITextUndoHistory history, ITextUndoTransaction parent, string description)
        {
            Check.ArgumentNull(nameof(history), history);
            Check.ArgumentStringNullOrEmpty(nameof(description), description);

            _history = history as UndoHistoryImpl;
            Check.ArgumentNull(nameof(history), _history);

            _parent = parent as UndoTransactionImpl;
            Check.Argument(nameof(parent), () => _parent != null || parent == null);

            Description = description;

            _state       = UndoTransactionState.Open;
            _primitives  = new List <ITextUndoPrimitive>();
            _mergePolicy = NullMergeUndoTransactionPolicy.Instance;
            IsReadOnly   = true;
        }
コード例 #12
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
        /// <summary>
        /// This is how the transactions alert their containing history that they have finished
        /// (likely from the Dispose() method).
        /// </summary>
        /// <param name="transaction">This is the transaction that's finishing. It should match the history's current transaction.
        /// If it does not match, then the current transaction will be discarded and an exception will be thrown.</param>
        public void EndTransaction(ITextUndoTransaction transaction)
        {
            if (_currentTransaction != transaction)
            {
                _currentTransaction = null;
                throw new InvalidOperationException("Strings.EndTransactionOutOfOrder");
            }

            // only add completed transactions to their parents (or the stack)
            if (_currentTransaction.State == UndoTransactionState.Completed)
            {
                if (_currentTransaction.Parent == null) // stack bottomed out!
                {
                    MergeOrPushToUndoStack(_currentTransaction);
                }
            }

            _currentTransaction = _currentTransaction.Parent as UndoTransactionImpl;
        }
コード例 #13
0
ファイル: UndoHistoryImpl.cs プロジェクト: zachwieja/RTVS
        /// <summary>
        /// Performs a redo operation and places the primitives on the redo stack, up until (and
        /// including) the transaction indicated. This is called by the linked undo transaction that
        /// is aware of the linking relationship between transactions, and it does not call back into
        /// the transactions' public Redo().
        /// </summary>
        /// <param name="transaction"></param>
        public void RedoInIsolation(UndoTransactionImpl transaction)
        {
            TextUndoHistoryState originalState = _state;

            _state = TextUndoHistoryState.Redoing;
            using (new AutoEnclose(delegate { this._state = originalState; })) {
                if (_redoStack.Contains(transaction))
                {
                    UndoTransactionImpl redone = null;
                    while (redone != transaction)
                    {
                        UndoTransactionImpl ut = _redoStack.Pop() as UndoTransactionImpl;
                        ut.Do();
                        _undoStack.Push(ut);

                        RaiseUndoRedoHappened(_state, ut);

                        redone = ut;
                    }
                }
            }
        }
コード例 #14
0
        /// <summary>
        /// Creates a new transaction, nests it in the previously current transaction, and marks it current.
        /// If there is a redo stack, it gets cleared.
        /// UNDONE: should the redo-clearing happen now or when the new transaction is committed?
        /// </summary>
        /// <param name="description">A string description for the transaction.</param>
        /// <returns></returns>
        public ITextUndoTransaction CreateTransaction(string description) {
            if (string.IsNullOrEmpty(description)) {
                throw new ArgumentException("description", string.Format(CultureInfo.CurrentUICulture, "Strings.ArgumentCannotBeNull {0} {1}", "CreateTransaction", "description"));
            }

            // If there is a pending transaction that has already been completed, we should not be permitted
            // to open a new transaction, since it cannot later be added to its parent.
            if ((_currentTransaction != null) && (_currentTransaction.State != UndoTransactionState.Open)) {
                throw new InvalidOperationException("Strings.CannotCreateTransactionWhenCurrentTransactionNotOpen");
            }

            // new transactions that are visible should clear the redo stack.
            if (_currentTransaction == null) {
                foreach (var textUndoTransaction in _redoStack) {
                    var redoTransaction = (UndoTransactionImpl) textUndoTransaction;
                    redoTransaction.Invalidate();
                }

                _redoStack.Clear();
            }

            UndoTransactionImpl newTransaction = new UndoTransactionImpl(this, _currentTransaction, description);

            _currentTransaction = newTransaction;

            return _currentTransaction;
        }
コード例 #15
0
        /// <summary>
        /// This is how the transactions alert their containing history that they have finished
        /// (likely from the Dispose() method). 
        /// </summary>
        /// <param name="transaction">This is the transaction that's finishing. It should match the history's current transaction.
        /// If it does not match, then the current transaction will be discarded and an exception will be thrown.</param>
        public void EndTransaction(ITextUndoTransaction transaction) {
            if (_currentTransaction != transaction) {
                _currentTransaction = null;
                throw new InvalidOperationException("Strings.EndTransactionOutOfOrder");
            }

            // only add completed transactions to their parents (or the stack)
            if (_currentTransaction.State == UndoTransactionState.Completed) {
                if (_currentTransaction.Parent == null) // stack bottomed out!
                {
                    MergeOrPushToUndoStack(_currentTransaction);
                }
            }

            _currentTransaction = _currentTransaction.Parent as UndoTransactionImpl;
        }
コード例 #16
0
        /// <summary>
        /// This does two different things, depending on the MergeUndoTransactionPolicys in question.
        /// It either simply pushes the current transaction to the undo stack, OR it merges it with
        /// the most recent item in the stack.
        /// </summary>
        private void MergeOrPushToUndoStack(UndoTransactionImpl transaction) {
            ITextUndoTransaction transactionAdded;
            TextUndoTransactionCompletionResult transactionResult;

            UndoTransactionImpl utPrevious = _undoStack.Count > 0 ? _undoStack.Peek() as UndoTransactionImpl : null;
            if (utPrevious != null && ProceedWithMerge(transaction, utPrevious)) {
                // Temporarily make utPrevious non-read-only, during merge.
                utPrevious.IsReadOnly = false;
                try {
                    transaction.MergePolicy.PerformTransactionMerge(utPrevious, transaction);
                } finally {
                    utPrevious.IsReadOnly = true;
                }

                // utPrevious is already on the undo stack, so we don't need to add it; but report
                // it as the added transaction in the UndoTransactionCompleted event.
                transactionAdded = utPrevious;
                transactionResult = TextUndoTransactionCompletionResult.TransactionMerged;
            } else {
                _undoStack.Push(transaction);

                transactionAdded = transaction;
                transactionResult = TextUndoTransactionCompletionResult.TransactionAdded;
            }

            RaiseUndoTransactionCompleted(transactionAdded, transactionResult);
        }
コード例 #17
0
        private bool ProceedWithMerge(UndoTransactionImpl transaction1, UndoTransactionImpl transaction2) {
            UndoHistoryRegistryImpl registry = UndoHistoryRegistry;

            return transaction1.MergePolicy != null
                && transaction2.MergePolicy != null
                && transaction1.MergePolicy.TestCompatiblePolicy(transaction2.MergePolicy)
                && transaction1.MergePolicy.CanMerge(transaction1, transaction2);
        }
コード例 #18
0
 /// <summary>
 /// Copies all of the primitives from the given transaction, and appends them to the UndoPrimitives list.
 /// </summary>
 /// <param name="transaction">The UndoTransactionImpl to copy from.</param>
 public void CopyPrimitivesFrom(UndoTransactionImpl transaction) {
     foreach (ITextUndoPrimitive p in transaction.UndoPrimitives) {
         AddUndo(p);
     }
 }
コード例 #19
0
        /// <summary>
        /// Performs a redo operation and places the primitives on the redo stack, up until (and 
        /// including) the transaction indicated. This is called by the linked undo transaction that
        /// is aware of the linking relationship between transactions, and it does not call back into
        /// the transactions' public Redo().
        /// </summary>
        /// <param name="transaction"></param>
        public void RedoInIsolation(UndoTransactionImpl transaction) {
            TextUndoHistoryState originalState = _state;
            _state = TextUndoHistoryState.Redoing;
            using (new AutoEnclose(delegate { this._state = originalState; })) {
                if (_redoStack.Contains(transaction)) {
                    UndoTransactionImpl redone = null;
                    while (redone != transaction) {
                        UndoTransactionImpl ut = _redoStack.Pop() as UndoTransactionImpl;
                        ut.Do();
                        _undoStack.Push(ut);

                        RaiseUndoRedoHappened(_state, ut);

                        redone = ut;
                    }
                }
            }
        }