// Helper for PasteTextFragment private static void PasteMergeableTextFragment(TextElement fragment, TextRange range, TextPointer insertionPosition) { TextPointer fragmentStart; TextPointer fragmentEnd; if (fragment is Span) { // Split structure at insertion point in target insertionPosition = TextRangeEdit.SplitFormattingElements(insertionPosition, /*keepEmptyFormatting:*/false); Invariant.Assert(insertionPosition.Parent is Paragraph, "insertionPosition must be in a scope of a Paragraph after splitting formatting elements"); // Move the whole Span into the insertion point fragment.RepositionWithContent(insertionPosition); // Store edge positions of inserted content fragmentStart = fragment.ElementStart; fragmentEnd = fragment.ElementEnd; // Remove wrapper from a tree fragment.Reposition(null, null); ValidateMergingPositions(typeof(Inline), fragmentStart, fragmentEnd); // Transfer inheritable contextual properties ApplyContextualProperties(fragmentStart, fragmentEnd, fragment); } else { // Correct leading nested List elements in the fragment CorrectLeadingNestedLists((Section)fragment); // Split a paragraph at insertion position bool needFirstParagraphMerging = SplitParagraphForPasting(ref insertionPosition); // Move the whole Section into the insertion point fragment.RepositionWithContent(insertionPosition); // Store edge positions of inserted content fragmentStart = fragment.ElementStart; fragmentEnd = fragment.ElementEnd.GetPositionAtOffset(0, LogicalDirection.Forward); // need forward orientation to stick with the following content during merge at fragmentStart position // And unwrap the root Section fragment.Reposition(null, null); ValidateMergingPositions(typeof(Block), fragmentStart, fragmentEnd); // Transfer inheritable contextual properties ApplyContextualProperties(fragmentStart, fragmentEnd, fragment); // Merge paragraphs on fragment boundaries if (needFirstParagraphMerging) { MergeParagraphsAtPosition(fragmentStart, /*mergingOnFragmentStart:*/true); } // Get an indication that we need to merge last paragraph if (!((Section)fragment).HasTrailingParagraphBreakOnPaste) { MergeParagraphsAtPosition(fragmentEnd, /*mergingOnFragmentStart:*/false); } } // // For paragraph pasting move range end to the following paragraph, because // it must include an ending paragraph break (in case of no-merging) if (fragment is Section && ((Section)fragment).HasTrailingParagraphBreakOnPaste) { fragmentEnd = fragmentEnd.GetInsertionPosition(LogicalDirection.Forward); } // Select pasted content range.Select(fragmentStart, fragmentEnd); }
/// <summary> /// Inserts a TextElement at this TextPointer's position. /// </summary> /// <param name="textElement"> /// ContentElement to insert. /// </param> /// <remarks> /// The LogicalDirection property specifies whether this TextPointer /// will be positioned before or after the TextElement. /// </remarks> /// <exception cref="ArgumentException"> /// Throws ArgumentException is textElement is not valid /// according to flow schema. /// </exception> /// <exception cref="InvalidOperationException"> /// Throws InvalidOperationException if textElement cannot be inserted /// at this position because it belongs to another tree. /// </exception> internal void InsertTextElement(TextElement textElement) { Invariant.Assert(textElement != null); _tree.EmptyDeadPositionList(); SyncToTreeGeneration(); ValidationHelper.ValidateChild(this, textElement, "textElement"); if (textElement.Parent != null) { throw new InvalidOperationException(SR.Get(SRID.TextPointer_CannotInsertTextElementBecauseItBelongsToAnotherTree)); } textElement.RepositionWithContent(this); }