/// <summary> /// Raises the <see cref="Changed"/> event. /// </summary> /// <remarks> /// <strong>Notes to Inheritors:</strong> When overriding <see cref="OnChanged"/> in a derived /// class, be sure to call the base class's <see cref="OnChanged"/> method so that registered /// delegates receive the event. /// </remarks> protected virtual void OnChanged(DocumentChangeEventArgs eventArgs) // [DIGITALRUNE] Use protected virtual method to raise Changed event. { var handler = Changed; if (handler != null) handler(this, eventArgs); }
public void ChangeComplete(DocumentChangeEventArgs e) { foreach (ILineTracker lt in lineTrackers) { lt.ChangeComplete(e); } }
void ILineTracker.ChangeComplete(DocumentChangeEventArgs e) { ILineTracker targetTracker = targetObject.Target as ILineTracker; if (targetTracker != null) targetTracker.ChangeComplete(e); else Deregister(); }
/// <summary> /// Updates the start and end offsets of all segments stored in this collection. /// </summary> /// <param name="e">DocumentChangeEventArgs instance describing the change to the document.</param> public void UpdateOffsets(DocumentChangeEventArgs e) { if (e == null) throw new ArgumentNullException("e"); if (isConnectedToDocument) throw new InvalidOperationException("This TextSegmentCollection will automatically update offsets; do not call UpdateOffsets manually!"); OnDocumentChanged(e); CheckProperties(); }
private void DocumentOnChanged(object sender, DocumentChangeEventArgs e) { SetCurrent(); var textChangeRange = new TextChangeRange( new TextSpan(e.Offset, e.RemovalLength), e.RemovalLength == 0 ? e.InsertionLength : e.RemovalLength); OnTextChanged(new TextChangeEventArgs(_before, CurrentText, textChangeRange)); }
void document_Changing(object sender, DocumentChangeEventArgs e) { if (state == StatePlayback) { throw new InvalidOperationException("Document changes during undo/redo operations are not allowed."); } TextDocument document = (TextDocument)sender; Push(new DocumentChangeOperation(document, e)); }
public void ChangeComplete(DocumentChangeEventArgs e) { if (_lineNumberRemoved > -1) { _bookmarkManager.AdjustLineOffsets(AdjustTypes.Deleted, _lineNumberRemoved, e.RemovalLength); _lineNumberRemoved = -1; } _bookmarkManager.RecalculateOffsets(_textArea, BookmarkType.Breakpoint, 1); }
private void OnAvDocChanged(object sender, DocumentChangeEventArgs e) { if (_loading) return; _version++; Modified = true; EventHandler<DocumentChangeEventArgs> handler = Changed; if (handler != null) handler(sender, e); }
void document_Changing(object sender, DocumentChangeEventArgs e) { TextDocument document = (TextDocument)sender; Push(new DocumentChangeOperation( document, e.Offset, document.GetText(e.Offset, e.RemovalLength), e.InsertedText)); }
/// <inheritdoc/> public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { if (e == null) throw new ArgumentNullException("e"); return Selection.Create( textArea, new TextViewPosition(textArea.Document.GetLocation(e.GetNewOffset(startOffset, AnchorMovementType.Default)), start.VisualColumn), new TextViewPosition(textArea.Document.GetLocation(e.GetNewOffset(endOffset, AnchorMovementType.Default)), end.VisualColumn) ); }
void OnDocumentChanged(DocumentChangeEventArgs e) { OffsetChangeMap map = e.OffsetChangeMapOrNull; if (map != null) { foreach (OffsetChangeMapEntry entry in map) { UpdateOffsetsInternal(entry); } } else { UpdateOffsetsInternal(e.CreateSingleChangeMapEntry()); } }
void ILineTracker.ChangeComplete(DocumentChangeEventArgs e) { if (targetObject.Target is ILineTracker targetTracker) { targetTracker.ChangeComplete(e); } else { Deregister(); } }
/// <inheritdoc/> public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { if (e == null) throw new ArgumentNullException("e"); TextViewPosition newStart = start; TextViewPosition newEnd = end; // by changing the existing TextViewPosition, we preserve the VisualColumn (though it might become invalid) // and the IsAtEndOfLine property. newStart.Location = textArea.Document.GetLocation(e.GetNewOffset(startOffset, AnchorMovementType.Default)); newEnd.Location = textArea.Document.GetLocation(e.GetNewOffset(endOffset, AnchorMovementType.Default)); return Selection.Create(textArea, newStart, newEnd); }
private void DocumentOnChanged(object sender, DocumentChangeEventArgs e) { if (_updatding) return; var oldText = _currentText; var textSpan = new TextSpan(e.Offset, e.RemovalLength); var textChangeRange = new TextChangeRange(textSpan, e.InsertionLength); _currentText = _currentText.WithChanges(new TextChange(textSpan, e.InsertedText?.Text ?? string.Empty)); TextChanged?.Invoke(this, new TextChangeEventArgs(oldText, _currentText, textChangeRange)); }
void OnDocumentChanged(DocumentChangeEventArgs e) { foldings.UpdateOffsets(e); FoldingSection s = foldings.FindFirstSegmentWithStartAfter(e.Offset); while (s != null && s.StartOffset == e.Offset) { FoldingSection next = foldings.GetNextSegment(s); if (s.Length == 0) { RemoveFolding(s); } s = next; } }
void ILineTracker.ChangeComplete(DocumentChangeEventArgs e) { ILineTracker targetTracker = targetObject.Target as ILineTracker; if (targetTracker != null) { targetTracker.ChangeComplete(e); } else { Deregister(); } }
/// <summary> /// Replaces text. /// Runtime: /// for updating the text buffer: m=size of new text, d=distance to last change /// usual: O(m+d) /// rare: O(m+n) /// for updating the document lines: O(m*log n), m=number of changed lines /// </summary> public void Replace(int offset, int length, string text) { if (inDocumentChanging) { throw new InvalidOperationException("Cannot change document within another document change."); } BeginUpdate(); // protect document change against corruption by other changes inside the event handlers inDocumentChanging = true; try { VerifyRange(offset, length); if (text == null) { throw new ArgumentNullException("text"); } if (length == 0 && text.Length == 0) { return; } fireTextChanged = true; DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, length, text); // fire DocumentChanging event if (Changing != null) { Changing(this, args); } DelayedEvents delayedEvents = new DelayedEvents(); // now do the real work anchorTree.RemoveText(offset, length, delayedEvents); ReplaceInternal(offset, length, text); anchorTree.InsertText(offset, text.Length); delayedEvents.RaiseEvents(); // fire DocumentChanged event if (Changed != null) { Changed(this, args); } } finally { inDocumentChanging = false; EndUpdate(); } }
internal void Push(TextDocument document, DocumentChangeEventArgs e) { if (state == StatePlayback) { throw new InvalidOperationException("Document changes during undo/redo operations are not allowed."); } if (state == StatePlaybackModifyDocument) { state = StatePlayback; // allow only 1 change per expected modification } else { Push(new DocumentChangeOperation(document, e)); } }
void OnDocumentChanged(DocumentChangeEventArgs e) { foldings.UpdateOffsets(e); int newEndOffset = e.Offset + e.InsertionLength; // extend end offset to the end of the line (including delimiter) var endLine = document.GetLineByOffset(newEndOffset); newEndOffset = endLine.Offset + endLine.TotalLength; foreach (var affectedFolding in foldings.FindOverlappingSegments(e.Offset, newEndOffset - e.Offset)) { if (affectedFolding.Length == 0) { RemoveFolding(affectedFolding); } else { affectedFolding.ValidateCollapsedLineSections(); } } }
/// <inheritdoc/> public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { if (e == null) throw new ArgumentNullException("e"); int newStartOffset, newEndOffset; if (startOffset <= endOffset) { newStartOffset = e.GetNewOffset(startOffset, AnchorMovementType.Default); newEndOffset = Math.Max(newStartOffset, e.GetNewOffset(endOffset, AnchorMovementType.BeforeInsertion)); } else { newEndOffset = e.GetNewOffset(endOffset, AnchorMovementType.Default); newStartOffset = Math.Max(newEndOffset, e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion)); } return Selection.Create( textArea, new TextViewPosition(textArea.Document.GetLocation(newStartOffset), start.VisualColumn), new TextViewPosition(textArea.Document.GetLocation(newEndOffset), end.VisualColumn) ); }
internal ChangeTrackingCheckpoint(object documentIdentifier, DocumentChangeEventArgs value, int id) { this.documentIdentifier = documentIdentifier; this.value = value; this.id = id; }
void DoReplace(int offset, int length, string newText, OffsetChangeMap offsetChangeMap) { if (length == 0 && newText.Length == 0) return; // trying to replace a single character in 'Normal' mode? // for single characters, 'CharacterReplace' mode is equivalent, but more performant // (we don't have to touch the anchorTree at all in 'CharacterReplace' mode) if (length == 1 && newText.Length == 1 && offsetChangeMap == null) offsetChangeMap = OffsetChangeMap.Empty; string removedText = rope.ToString(offset, length); DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap); // fire DocumentChanging event if (Changing != null) Changing(this, args); cachedText = null; // reset cache of complete document text fireTextChanged = true; DelayedEvents delayedEvents = new DelayedEvents(); lock (lockObject) { // create linked list of checkpoints, if required if (currentCheckpoint != null) { currentCheckpoint = currentCheckpoint.Append(args); } // now update the textBuffer and lineTree if (offset == 0 && length == rope.Length) { // optimize replacing the whole document rope.Clear(); rope.InsertText(0, newText); lineManager.Rebuild(); } else { rope.RemoveRange(offset, length); lineManager.Remove(offset, length); #if DEBUG lineTree.CheckProperties(); #endif rope.InsertText(offset, newText); lineManager.Insert(offset, newText); #if DEBUG lineTree.CheckProperties(); #endif } } // update text anchors if (offsetChangeMap == null) { anchorTree.HandleTextChange(args.CreateSingleChangeMapEntry(), delayedEvents); } else { foreach (OffsetChangeMapEntry entry in offsetChangeMap) { anchorTree.HandleTextChange(entry, delayedEvents); } } // raise delayed events after our data structures are consistent again delayedEvents.RaiseEvents(); // fire DocumentChanged event if (Changed != null) Changed(this, args); }
private void DocumentOnChanging(object sender, DocumentChangeEventArgs e) { _before = CurrentText; }
/// <inheritdoc/> public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { if (e == null) throw new ArgumentNullException("e"); return new SimpleSelection( e.GetNewOffset(startOffset, AnchorMovementType.Default), e.GetNewOffset(endOffset, AnchorMovementType.Default) ); }
void OnDocumentChanged(DocumentChangeEventArgs e) { caret.OnDocumentChanged(e); this.Selection = selection.UpdateOnDocumentChange(e); }
void document_Changed(object sender, DocumentChangeEventArgs e) { if (DocumentChanged != null) DocumentChanged(this, new TextChangeEventArgs(e.Offset, e.RemovedText, e.InsertedText)); }
void textArea_Document_Changing(object sender, DocumentChangeEventArgs e) { if (e.Offset + e.RemovalLength == this.StartOffset && e.RemovalLength > 0) { Close(); // removal immediately in front of completion segment: close the window // this is necessary when pressing backspace after dot-completion } if (e.Offset == StartOffset && e.RemovalLength == 0 && ExpectInsertionBeforeStart) { StartOffset = e.GetNewOffset(StartOffset, AnchorMovementType.AfterInsertion); this.ExpectInsertionBeforeStart = false; } else { StartOffset = e.GetNewOffset(StartOffset, AnchorMovementType.BeforeInsertion); } EndOffset = e.GetNewOffset(EndOffset, AnchorMovementType.AfterInsertion); }
void textArea_Document_Changing(object sender, DocumentChangeEventArgs e) { if (e.Offset == startOffset && e.RemovalLength == 0 && ExpectInsertionBeforeStart) { startOffset = e.GetNewOffset(startOffset, AnchorMovementType.AfterInsertion); this.ExpectInsertionBeforeStart = false; } else { startOffset = e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion); } endOffset = e.GetNewOffset(endOffset, AnchorMovementType.AfterInsertion); }
void document_Changing(object sender, DocumentChangeEventArgs e) { TextDocument document = (TextDocument)sender; Push(new DocumentChangeOperation(document, e)); }
public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { return this; }
void ILineTracker.ChangeComplete(DocumentChangeEventArgs e) { }
void document_Changed(object sender, DocumentChangeEventArgs e) { if (DocumentChanged != null) DocumentChanged(this, e); }
void DoReplace(int offset, int length, string newText, OffsetChangeMap offsetChangeMap) { if (length == 0 && newText.Length == 0) { return; } // trying to replace a single character in 'Normal' mode? // for single characters, 'CharacterReplace' mode is equivalent, but more performant // (we don't have to touch the anchorTree at all in 'CharacterReplace' mode) if (length == 1 && newText.Length == 1 && offsetChangeMap == null) { offsetChangeMap = OffsetChangeMap.Empty; } string removedText = rope.ToString(offset, length); DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap); // fire DocumentChanging event if (Changing != null) { Changing(this, args); } cachedText = null; // reset cache of complete document text fireTextChanged = true; DelayedEvents delayedEvents = new DelayedEvents(); lock (lockObject) { // create linked list of checkpoints, if required if (currentCheckpoint != null) { currentCheckpoint = currentCheckpoint.Append(args); } // now update the textBuffer and lineTree if (offset == 0 && length == rope.Length) { // optimize replacing the whole document rope.Clear(); rope.InsertText(0, newText); lineManager.Rebuild(); } else { rope.RemoveRange(offset, length); lineManager.Remove(offset, length); #if DEBUG lineTree.CheckProperties(); #endif rope.InsertText(offset, newText); lineManager.Insert(offset, newText); #if DEBUG lineTree.CheckProperties(); #endif } } // update text anchors if (offsetChangeMap == null) { anchorTree.HandleTextChange(args.CreateSingleChangeMapEntry(), delayedEvents); } else { foreach (OffsetChangeMapEntry entry in offsetChangeMap) { anchorTree.HandleTextChange(entry, delayedEvents); } } // raise delayed events after our data structures are consistent again delayedEvents.RaiseEvents(); // fire DocumentChanged event if (Changed != null) { Changed(this, args); } }
internal void Push(TextDocument document, DocumentChangeEventArgs e) { if (state == StatePlayback) throw new InvalidOperationException("Document changes during undo/redo operations are not allowed."); if (state == StatePlaybackModifyDocument) state = StatePlayback; // allow only 1 change per expected modification else Push(new DocumentChangeOperation(document, e)); }
internal void OnDocumentChanged(DocumentChangeEventArgs e) { InvalidateVisualColumn(); if (storedCaretOffset >= 0) { // If the caret is at the end of a selection, we don't expand the selection if something // is inserted at the end. Thus we also need to keep the caret in front of the insertion. AnchorMovementType caretMovementType; if (!textArea.Selection.IsEmpty && storedCaretOffset == textArea.Selection.SurroundingSegment.EndOffset) caretMovementType = AnchorMovementType.BeforeInsertion; else caretMovementType = AnchorMovementType.Default; int newCaretOffset = e.GetNewOffset(storedCaretOffset, caretMovementType); TextDocument document = textArea.Document; if (document != null) { // keep visual column this.Position = new TextViewPosition(document.GetLocation(newCaretOffset), position.VisualColumn); } } storedCaretOffset = -1; }
internal void OnDocumentChanged(DocumentChangeEventArgs e) { InvalidateVisualColumn(); if (storedCaretOffset >= 0) { int newCaretOffset = e.GetNewOffset(storedCaretOffset, AnchorMovementType.Default); TextDocument document = textArea.Document; if (document != null) { // keep visual column this.Position = new TextViewPosition(document.GetLocation(newCaretOffset), position.VisualColumn); } } storedCaretOffset = -1; }
public DocumentChangeOperation(TextDocument document, DocumentChangeEventArgs change) { this.document = document; this.change = change; }
internal ChangeTrackingCheckpoint Append(DocumentChangeEventArgs change) { Debug.Assert(next == null); next = new ChangeTrackingCheckpoint(documentIdentifier, change, unchecked (id + 1)); return(next); }
private void EditorDocumentChanged(object sender, DocumentChangeEventArgs e) { if (e.InsertionLength > 0) { this._lastCaretPos = this._editor.CaretOffset; if (this._autoCompleter != null) { this._endAutoComplete = true; } } else if (e.RemovalLength > 0) { this._lastCaretPos = this._editor.CaretOffset; } }
internal ChangeTrackingCheckpoint Append(DocumentChangeEventArgs change) { Debug.Assert(this.next == null); this.next = new ChangeTrackingCheckpoint(this.documentIdentifier, change, unchecked( this.id + 1 )); return this.next; }
/// <inheritdoc/> public override Selection UpdateOnDocumentChange(DocumentChangeEventArgs e) { TextLocation newStartLocation = textArea.Document.GetLocation(e.GetNewOffset(topLeftOffset, AnchorMovementType.AfterInsertion)); TextLocation newEndLocation = textArea.Document.GetLocation(e.GetNewOffset(bottomRightOffset, AnchorMovementType.BeforeInsertion)); return new RectangleSelection(textArea, new TextViewPosition(newStartLocation, GetVisualColumnFromXPos(newStartLocation.Line, startXPos)), new TextViewPosition(newEndLocation, GetVisualColumnFromXPos(newEndLocation.Line, endXPos))); }
void OnDocumentChanged(DocumentChangeEventArgs e) { RemoveText(e.Offset, e.RemovalLength); InsertText(e.Offset, e.InsertionLength); }
void DoReplace(int offset, int length, ITextSource newText, OffsetChangeMap offsetChangeMap) { if (length == 0 && newText.TextLength == 0) { return; } // trying to replace a single character in 'Normal' mode? // for single characters, 'CharacterReplace' mode is equivalent, but more performant // (we don't have to touch the anchorTree at all in 'CharacterReplace' mode) if (length == 1 && newText.TextLength == 1 && offsetChangeMap == null) { offsetChangeMap = OffsetChangeMap.Empty; } ITextSource removedText; if (length == 0) { removedText = StringTextSource.Empty; } else if (length < 100) { removedText = new StringTextSource(rope.ToString(offset, length)); } else { // use a rope if the removed string is long removedText = new RopeTextSource(rope.GetRange(offset, length)); } DocumentChangeEventArgs args = new DocumentChangeEventArgs(offset, removedText, newText, offsetChangeMap); // fire DocumentChanging event if (Changing != null) { Changing(this, args); } if (textChanging != null) { textChanging(this, args); } undoStack.Push(this, args); cachedText = null; // reset cache of complete document text fireTextChanged = true; DelayedEvents delayedEvents = new DelayedEvents(); lock (lockObject) { // create linked list of checkpoints versionProvider.AppendChange(args); // now update the textBuffer and lineTree if (offset == 0 && length == rope.Length) { // optimize replacing the whole document rope.Clear(); if (newText is RopeTextSource newRopeTextSource) { rope.InsertRange(0, newRopeTextSource.GetRope()); } else { rope.InsertText(0, newText.Text); } lineManager.Rebuild(); } else { rope.RemoveRange(offset, length); lineManager.Remove(offset, length); #if DEBUG lineTree.CheckProperties(); #endif if (newText is RopeTextSource newRopeTextSource) { rope.InsertRange(offset, newRopeTextSource.GetRope()); } else { rope.InsertText(offset, newText.Text); } lineManager.Insert(offset, newText); #if DEBUG lineTree.CheckProperties(); #endif } } // update text anchors if (offsetChangeMap == null) { anchorTree.HandleTextChange(args.CreateSingleChangeMapEntry(), delayedEvents); } else { foreach (OffsetChangeMapEntry entry in offsetChangeMap) { anchorTree.HandleTextChange(entry, delayedEvents); } } lineManager.ChangeComplete(args); // raise delayed events after our data structures are consistent again delayedEvents.RaiseEvents(); // fire DocumentChanged event if (Changed != null) { Changed(this, args); } if (textChanged != null) { textChanged(this, args); } }