예제 #1
0
        /// <remarks>
        /// Edits are queued up by our TextBufferChanged handler and then we finally add them to the
        /// undo stack here in response to PostChanged.  The reason and history behind why we do this
        /// is as follows:
        ///
        /// Originally this was done for VB commit, which uses undo events (i.e. TransactionCompleted) to
        /// trigger commit.  Their commit logic relies on the buffer being in a state such that applying
        /// an edit synchronously raises a Changed event (which is always the case for PostChanged, but
        /// not for Changed if there are nested edits).
        ///
        /// JaredPar made a change (CS 1182244) that allowed VB to detect that UndoTransactionCompleted
        /// was being fired from a nested edit, and therefore delay the actual commit until the following
        /// PostChanged event.
        ///
        /// So this allowed us to move TextBufferUndoManager back to adding undo actions directly
        /// from the TextBufferChanged handler (CS 1285117).  This is preferable, as otherwise there's a
        /// "delay" between when the edit happens and when we record the edit on the undo stack,
        /// allowing other people to stick something on the undo stack (i.e. from
        /// their ITextBuffer.Changed handler) in between.  The result is actions being "out-of-order"
        /// on the undo stack.
        ///
        /// Unfortunately, it turns out VB snippets actually rely on this "out-of-order" behavior
        /// (see Dev10 834740) and so we are forced to revert CS 1285117) and return to the model
        /// where we queue up edits and delay adding them to the undo stack until PostChanged.
        ///
        /// It would be good to revisit this at again, but we would need to work with VB
        /// to fix their snippets / undo behavior, and verify that VB commit is also unaffected.
        /// </remarks>
        private void TextBufferPostChanged(object sender, EventArgs e)
        {
            // Only process a top level PostChanged event.  Nested events will continue to process TextChange events
            // which are added to the queue and will be processed below
            if (_inPostChanged)
            {
                return;
            }

            _inPostChanged = true;
            try
            {
                // Do not do a foreach loop here.  It's perfectly possible, and in fact expected, that the Complete
                // method below can trigger a series of events which leads to a nested edit and another
                // ITextBuffer::Changed.  That event will add to the _editVersionList queue and hence break a
                // foreach loop
                while (_editVersionList.Count > 0)
                {
                    var cur = _editVersionList.Dequeue();
                    using (ITextUndoTransaction undoTransaction = _undoHistory.CreateTransaction(Strings.TextBufferChanged))
                    {
                        TextBufferChangeUndoPrimitive undoPrimitive = new TextBufferChangeUndoPrimitive(_undoHistory, cur);
                        undoTransaction.AddUndo(undoPrimitive);

                        undoTransaction.Complete();
                    }
                }
            }
            finally
            {
                _editVersionList.Clear();   // Ensure we cleanup state in the face of an exception
                _inPostChanged = false;
            }
        }
예제 #2
0
 public void Dispose()
 {
     _selectionTracker.EndTracking();
     _transaction.AddUndo(new EndSelectionTrackingUndoUnit(_selectionTracker, _textBuffer));
     _transaction.Complete();
     _transaction.Dispose();
 }
예제 #3
0
        public SelectionUndo(ISelectionTracker selectionTracker, ITextBufferUndoManagerProvider undoManagerProvider, string transactionName, bool automaticTracking)
        {
            _selectionTracker = selectionTracker;
            var undoManager = undoManagerProvider.GetTextBufferUndoManager(selectionTracker.TextView.TextBuffer);

            ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(transactionName);

            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);
            _transaction.AddUndo(new StartSelectionTrackingUndoUnit(selectionTracker));

            _selectionTracker.StartTracking(automaticTracking);
        }
예제 #4
0
        public void Dispose()
        {
            if (!EditorShell.Current.IsUnitTestEnvironment)
            {
                _selectionTracker.EndTracking();

                _transaction.AddUndo(new EndSelectionTrackingUndoUnit(_selectionTracker));

                _transaction.Complete();
                _transaction.Dispose();
            }
        }
예제 #5
0
        public MassiveChange(ITextView textView, ITextBuffer textBuffer, ICompositionCatalog catalog, string description) {
            _textBuffer = textBuffer;

            var undoManagerProvider = catalog.ExportProvider.GetExportedValue<ITextBufferUndoManagerProvider>();
            var undoManager = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer);

            ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(description);
            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);

            _transaction.AddUndo(new StartMassiveChangeUndoUnit(_textBuffer));

            IREditorDocument document = REditorDocument.TryFromTextBuffer(_textBuffer);
            document?.BeginMassiveChange();
        }
예제 #6
0
        public SelectionUndo(ISelectionTracker selectionTracker, string transactionName, bool automaticTracking)
        {
            if (!EditorShell.Current.IsUnitTestEnvironment)
            {
                _selectionTracker = selectionTracker;

                var undoManagerProvider = EditorShell.Current.ExportProvider.GetExport <ITextBufferUndoManagerProvider>().Value;
                var undoManager         = undoManagerProvider.GetTextBufferUndoManager(selectionTracker.TextView.TextBuffer);

                ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(transactionName);
                _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);
                _transaction.AddUndo(new StartSelectionTrackingUndoUnit(selectionTracker));

                _selectionTracker.StartTracking(automaticTracking);
            }
        }
예제 #7
0
        public MassiveChange(ITextView textView, ITextBuffer textBuffer, ICoreShell shell, string description)
        {
            _textBuffer = textBuffer;

            var undoManagerProvider = shell.GetService <ITextBufferUndoManagerProvider>();
            var undoManager         = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer);

            ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(description);

            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);

            _transaction.AddUndo(new StartMassiveChangeUndoUnit(_textBuffer));

            IREditorDocument document = REditorDocument.TryFromTextBuffer(_textBuffer);

            document?.BeginMassiveChange();
        }
예제 #8
0
        public MassiveChange(ITextView textView, ITextBuffer textBuffer, IServiceContainer services, string description)
        {
            _textBuffer = textBuffer;

            var undoManagerProvider = services.GetService <ITextBufferUndoManagerProvider>();
            var undoManager         = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer);

            var innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(description);

            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);

            _transaction.AddUndo(new StartMassiveChangeUndoUnit(_textBuffer));

            var document = _textBuffer.GetEditorDocument <IREditorDocument>();

            document?.BeginMassiveChange();
        }
예제 #9
0
        public MassiveChange(ITextView textView, ITextBuffer textBuffer, string description)
        {
            _textBuffer = textBuffer;

            var undoManagerProvider = EditorShell.Current.ExportProvider.GetExport<ITextBufferUndoManagerProvider>().Value;
            var undoManager = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer);

            ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(description);
            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);

            _transaction.AddUndo(new StartMassiveChangeUndoUnit(_textBuffer));

            IREditorDocument document = REditorDocument.TryFromTextBuffer(_textBuffer);
            if(document != null) {
                document.BeginMassiveChange();
            }
        }
예제 #10
0
        public MassiveChange(ITextView textView, ITextBuffer textBuffer, string description)
        {
            _textBuffer = textBuffer;

            var undoManagerProvider = EditorShell.Current.ExportProvider.GetExport <ITextBufferUndoManagerProvider>().Value;
            var undoManager         = undoManagerProvider.GetTextBufferUndoManager(textView.TextBuffer);

            ITextUndoTransaction innerTransaction = undoManager.TextBufferUndoHistory.CreateTransaction(description);

            _transaction = new TextUndoTransactionThatRollsBackProperly(innerTransaction);

            _transaction.AddUndo(new StartMassiveChangeUndoUnit(_textBuffer));

            IREditorDocument document = REditorDocument.TryFromTextBuffer(_textBuffer);

            if (document != null)
            {
                document.BeginMassiveChange();
            }
        }
예제 #11
0
        public void Dispose()
        {
            IREditorDocument document = REditorDocument.TryFromTextBuffer(_textBuffer);
            bool             changed  = true;

            if (document != null)
            {
                changed = document.EndMassiveChange();
            }

            if (!changed)
            {
                _transaction.Cancel();
            }
            else
            {
                _transaction.AddUndo(new EndMassiveChangeUndoUnit(_textBuffer));
                _transaction.Complete();
            }

            _transaction.Dispose();
        }
예제 #12
0
        public void Dispose()
        {
            var document = _textBuffer.GetEditorDocument <IREditorDocument>();
            var changed  = true;

            if (document != null)
            {
                changed = document.EndMassiveChange();
            }

            if (!changed)
            {
                _transaction.Cancel();
            }
            else
            {
                _transaction.AddUndo(new EndMassiveChangeUndoUnit(_textBuffer));
                _transaction.Complete();
            }

            _transaction.Dispose();
        }