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); } }
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); }); }