void PositionChanged_ITextCaret(CaretLocationEventArgs args)
        {
            //Some unit tests don't initialize full UI representation of MonoTextEditor
            //which means they don't depend on ITextCaret implementation, so we can return here
            //If something is using MonoTextEditor directly(e.g. DiffView) and is not initializing ITextView
            //TextBuffer is null, in that case don't depend on ITextCaret implementation, so we can return here
            if (TextEditor?.TextBuffer == null)
            {
                return;
            }
            // MD doesn't fire textEditor.CaretPositionChanged until after the command has gone completely through the command chain.
            //   Too much VS stuff depends on it getting updated earlier, so we'll use this event which fires earlier.
            int position             = TextEditor.Caret.Offset;
            VirtualSnapshotPoint vsp = new VirtualSnapshotPoint(TextEditor.TextSnapshot, position);

            insertionPoint = vsp;
            if (args.CaretChangeReason == CaretChangeReason.Movement)
            {
                oldCaretLocation = args.Location;
                var oldOffset        = TextEditor.LocationToOffset(args.Location);
                var snapshotPoint    = new SnapshotPoint(TextEditor.TextSnapshot, oldOffset);
                var mappingPoint     = TextEditor.BufferGraph.CreateMappingPoint(snapshotPoint, PointTrackingMode.Positive);
                var oldCaretPosition = new CaretPosition(vsp, mappingPoint, _caretAffinity);
                var eventArgs        = new CaretPositionChangedEventArgs(TextEditor, oldCaretPosition, ((ITextCaret)this).Position);

                ITextCaret_PositionChanged?.Invoke(this, eventArgs);
            }
        }
Example #2
0
        void PositionChanged_ITextCaret(CaretLocationEventArgs args)
        {
            //Some unit tests don't initialize full UI representation of MonoTextEditor
            //which means they don't depend on ITextCaret implementation, so we can return here
            //If something is using MonoTextEditor directly(e.g. DiffView) and is not initializing ITextView
            //TextBuffer is null, in that case don't depend on ITextCaret implementation, so we can return here
            if (TextEditor?.TextBuffer == null)
            {
                return;
            }
            // MD doesn't fire textEditor.CaretPositionChanged until after the command has gone completely through the command chain.
            //   Too much VS stuff depends on it getting updated earlier, so we'll use this event which fires earlier.
            int position             = TextEditor.Caret.Offset;
            VirtualSnapshotPoint vsp = new VirtualSnapshotPoint(TextEditor.TextSnapshot, position);

            insertionPoint = vsp;
            if (args.CaretChangeReason == CaretChangeReason.Movement)
            {
                oldCaretLocation = args.Location;
                var snapShot     = args.Snapshot;
                var snapshotLine = snapShot.GetLineFromLineNumber(args.Location.Line - 1);
                if (snapshotLine == null)
                {
                    LoggingService.LogError("PositionChanged_ITextCaret line number : " + args.Location.Line + " is out of range.");
                    return;
                }
                var oldOffset        = snapshotLine.Start.Position + Math.Min(snapshotLine.Length, args.Location.Column - 1);
                var snapshotPoint    = new SnapshotPoint(snapShot, oldOffset);
                var mappingPoint     = TextEditor.BufferGraph.CreateMappingPoint(snapshotPoint, PointTrackingMode.Positive);
                var oldCaretPosition = new CaretPosition(vsp, mappingPoint, _caretAffinity);
                var eventArgs        = new CaretPositionChangedEventArgs(TextEditor, oldCaretPosition, ((ITextCaret)this).Position);

                ITextCaret_PositionChanged?.Invoke(this, eventArgs);
            }

            // Synchronize the MultiSelectionBroker with Caret.
            // In VS Editor 15.8 the MultiSelectionBroker is the single source of truth about carets and selections
            // (no selection / single caret, no selection / multiple carets, simple selection, block selection, multiple selections).
            // In our world, we still have our own Caret and Selection, so when our Caret moves, we need to synchronize
            // the MultiSelectionBroker to our values, and when the MultiSelectionBroker changes
            // (e.g. as a result of EditorOperations such as InsertNewLine), we need to synchronize our caret and selection
            // to the MultiSelectionBroker values.
            // Note that EditorOperations only updates the MultiSelectionBroker, it no longer moves caret or selection
            // (since in Editor 15.8 the Caret and Selection are shims implemented in terms of MultiSelectionBroker)
            // TODO: synchronize all our selections as well.
            TextEditorData.Parent.MultiSelectionBroker.PerformActionOnAllSelections(transformer => {
                transformer.MoveTo(vsp, select: false, PositionAffinity.Successor);
            });
        }