示例#1
0
        // Paste flow content into the current text selection
        // Returns false if pasting was not successful - assuming that the caller will choose another format for pasting
        private static bool PasteTextElement(TextEditor This, TextElement sectionOrSpan)
        {
            bool success = false;

            This.Selection.BeginChange();
            try
            {
                ((TextRange)This.Selection).SetXmlVirtual(sectionOrSpan);

                // Merge new Lists with surrounding Lists.
                TextRangeEditLists.MergeListsAroundNormalizedPosition((TextPointer)This.Selection.Start);
                TextRangeEditLists.MergeListsAroundNormalizedPosition((TextPointer)This.Selection.End);

                // Merge flow direction of the new content if it matches its surroundings.
                TextRangeEdit.MergeFlowDirection((TextPointer)This.Selection.Start);
                TextRangeEdit.MergeFlowDirection((TextPointer)This.Selection.End);

                success = true;
            }
            finally
            {
                This.Selection.EndChange();
            }

            return(success);
        }
 // Token: 0x06003AFD RID: 15101 RVA: 0x0010A660 File Offset: 0x00108860
 internal virtual void InsertEmbeddedUIElementVirtual(FrameworkElement embeddedElement)
 {
     Invariant.Assert(this.HasConcreteTextContainer, "Can't insert embedded object to non-TextContainer range!");
     Invariant.Assert(embeddedElement != null);
     TextRangeBase.BeginChange(this);
     try
     {
         this.Text = string.Empty;
         TextPointer textPointer = TextRangeEditTables.EnsureInsertionPosition(this.Start);
         Paragraph   paragraph   = textPointer.Paragraph;
         if (paragraph != null)
         {
             if (Paragraph.HasNoTextContent(paragraph))
             {
                 BlockUIContainer blockUIContainer = new BlockUIContainer(embeddedElement);
                 blockUIContainer.TextAlignment = TextRangeEdit.GetTextAlignmentFromHorizontalAlignment(embeddedElement.HorizontalAlignment);
                 paragraph.SiblingBlocks.InsertAfter(paragraph, blockUIContainer);
                 paragraph.SiblingBlocks.Remove(paragraph);
                 this.Select(blockUIContainer.ContentStart, blockUIContainer.ContentEnd);
             }
             else
             {
                 InlineUIContainer inlineUIContainer = new InlineUIContainer(embeddedElement);
                 TextPointer       textPointer2      = TextRangeEdit.SplitFormattingElements(this.Start, false);
                 textPointer2.InsertTextElement(inlineUIContainer);
                 this.Select(inlineUIContainer.ElementStart, inlineUIContainer.ElementEnd);
             }
         }
     }
     finally
     {
         TextRangeBase.EndChange(this);
     }
 }
示例#3
0
        // Predicate which returns true if list items in this range are within the scope of the same parent list.
        private static bool IsRangeWithinSingleList(TextRange range)
        {
            ListItem startListItem = TextPointerBase.GetListItem(range.Start);

            // Adjust range end so that it does not affect a following paragraph.
            TextPointer end         = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);
            ListItem    endListItem = TextPointerBase.GetListItem(end);

            // Check if the ListItems belong to one List wrapper.
            if (startListItem != null && endListItem != null && startListItem.Parent == endListItem.Parent)
            {
                return(true);
            }

            // In case of nested lists, it may be the case that start and end list item do not belong to one list wrapper,
            // yet no visual list boundary is crossed.
            // e.g.
            //  * aa
            //      * bb
            //      * cc
            // Special case so that list operations are applicable in this scenario.
            if (startListItem != null && endListItem != null)
            {
                while (end.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
                {
                    if (end.Parent == startListItem.Parent)
                    {
                        return(true);
                    }
                    end = end.GetNextContextPosition(LogicalDirection.Forward);
                }
            }

            return(false);
        }
示例#4
0
        // Returns true if all paragraphs in a range belong to the same block,
        // so they can be easily grouped and ungrouped.
        internal static bool IsListOperationApplicable(TextRange range)
        {
            // First check, if range start/end are parented by ListItems within the same parent list.
            if (IsRangeWithinSingleList(range))
            {
                return(true);
            }

            // Adjust range end so that it does not affect a following paragraph.
            TextPointer end = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);

            // Now try plain Paragraphs
            Block firstBlock = range.Start.ParagraphOrBlockUIContainer;
            Block lastBlock  = end.ParagraphOrBlockUIContainer;

            if (firstBlock != null && lastBlock != null && firstBlock.Parent == lastBlock.Parent)
            {
                return(true);
            }

            // Allow list editing at potential paragraph positions, this includes
            // positions in initial RichTextBox, empty TableCell, empty ListItem where paragraphs were not yet created.
            if (range.IsEmpty && TextPointerBase.IsAtPotentialParagraphPosition(range.Start))
            {
                return(true);
            }

            return(false);
        }
示例#5
0
        internal static void _OnApplyProperty(TextEditor This, DependencyProperty formattingProperty, object propertyValue, bool applyToParagraphs, PropertyValueAction propertyValueAction)
        {
            if (This == null || !This._IsEnabled || This.IsReadOnly || !This.AcceptsRichContent || !(This.Selection is TextSelection))
            {
                return;
            }

            // Check whether the property is known
            if (!TextSchema.IsParagraphProperty(formattingProperty) && !TextSchema.IsCharacterProperty(formattingProperty))
            {
                Invariant.Assert(false, "The property '" + formattingProperty.Name + "' is unknown to TextEditor");
                return;
            }

            TextSelection selection = (TextSelection)This.Selection;

            if (TextSchema.IsStructuralCharacterProperty(formattingProperty) &&
                !TextRangeEdit.CanApplyStructuralInlineProperty(selection.Start, selection.End))
            {
                // Ignore structural commands fires in inappropriate context.
                return;
            }

            TextEditorTyping._FlushPendingInputItems(This);

            // Forget previously suggested horizontal position
            TextEditorSelection._ClearSuggestedX(This);

            // Break merged typing sequence
            TextEditorTyping._BreakTypingSequence(This);

            // Apply property
            selection.ApplyPropertyValue(formattingProperty, propertyValue, applyToParagraphs, propertyValueAction);
        }
        // Token: 0x06003836 RID: 14390 RVA: 0x000FAA28 File Offset: 0x000F8C28
        private static void OnResetFormat(object target, ExecutedRoutedEventArgs args)
        {
            TextEditor textEditor = TextEditor._GetTextEditor(target);

            if (textEditor == null || !textEditor._IsEnabled || textEditor.IsReadOnly || !textEditor.AcceptsRichContent || !(textEditor.Selection.Start is TextPointer))
            {
                return;
            }
            TextEditorTyping._FlushPendingInputItems(textEditor);
            using (textEditor.Selection.DeclareChangeBlock())
            {
                TextPointer start = (TextPointer)textEditor.Selection.Start;
                TextPointer end   = (TextPointer)textEditor.Selection.End;
                if (textEditor.Selection.IsEmpty)
                {
                    TextSegment autoWord = TextRangeBase.GetAutoWord(textEditor.Selection);
                    if (autoWord.IsNull)
                    {
                        ((TextSelection)textEditor.Selection).ClearSpringloadFormatting();
                        return;
                    }
                    start = (TextPointer)autoWord.Start;
                    end   = (TextPointer)autoWord.End;
                }
                TextEditorSelection._ClearSuggestedX(textEditor);
                TextRangeEdit.CharacterResetFormatting(start, end);
            }
        }
        // Token: 0x06003B84 RID: 15236 RVA: 0x0010F178 File Offset: 0x0010D378
        internal static void IndentListItems(TextRange range)
        {
            ListItem immediateListItem  = TextPointerBase.GetImmediateListItem(range.Start);
            ListItem immediateListItem2 = TextPointerBase.GetImmediateListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End));

            if (immediateListItem == null || immediateListItem2 == null || immediateListItem.Parent != immediateListItem2.Parent || !(immediateListItem.Parent is List))
            {
                return;
            }
            ListItem previousListItem = immediateListItem.PreviousListItem;

            if (previousListItem == null)
            {
                return;
            }
            List element = (List)immediateListItem.Parent;
            List list    = (List)TextRangeEdit.InsertElementClone(immediateListItem.ElementStart, immediateListItem2.ElementEnd, element);

            previousListItem.Reposition(previousListItem.ContentStart, list.ElementEnd);
            Paragraph paragraph = immediateListItem2.Blocks.FirstBlock as Paragraph;

            if (paragraph != null)
            {
                List list2 = paragraph.NextBlock as List;
                if (list2 != null && list2.NextBlock == null)
                {
                    immediateListItem2.Reposition(immediateListItem2.ContentStart, list2.ElementStart);
                    list2.Reposition(null, null);
                }
            }
            TextRangeEditLists.MergeLists(list.ElementStart);
        }
示例#8
0
        /// <summary>
        /// Merges two naighboring lists ending and starting at position mergePosition
        /// </summary>
        /// <param name="mergePosition">
        /// Position at with two List elements are expected to appear next to each other
        /// </param>
        /// <returns>
        /// true if there were two mergeable List elements and merge happened.
        /// false if there is no pair of List elements at the mergePosition.
        /// </returns>
        internal static bool MergeLists(TextPointer mergePosition)
        {
            if (mergePosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementEnd ||
                mergePosition.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.ElementStart)
            {
                return(false);
            }

            List precedingList = mergePosition.GetAdjacentElement(LogicalDirection.Backward) as List;
            List followingList = mergePosition.GetAdjacentElement(LogicalDirection.Forward) as List;

            if (precedingList == null || followingList == null)
            {
                return(false);
            }

            precedingList.Reposition(precedingList.ContentStart, followingList.ElementEnd);
            followingList.Reposition(null, null);

            // We need to set appropriate FlowDirection property on the new List and its paragraph children.
            // We take the FlowDirection value from the preceding list.
            TextRangeEdit.SetParagraphProperty(precedingList.ElementStart, precedingList.ElementEnd,
                                               Paragraph.FlowDirectionProperty, precedingList.GetValue(Paragraph.FlowDirectionProperty));

            return(true);
        }
示例#9
0
        // Assumes that a range contains a sequence of same-level ListItems.
        // Converts all these ListItems into Paragraphs and
        // either adds them to preceding ListItem (as non-bulleted continuation)
        // or pulls them out of a List if they start in the beginning of a List
        internal static void ConvertListItemsToParagraphs(TextRange range)
        {
            ListItem firstListItem = TextPointerBase.GetListItem(range.Start);
            ListItem lastListItem  = TextPointerBase.GetListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End));

            // The range must be in a sequence of ListItems belonging to one List wrapper
            if (firstListItem == null || lastListItem == null || firstListItem.Parent != lastListItem.Parent || !(firstListItem.Parent is List))
            {
                return;
            }

            List listToRemove = null;

            ListItem leadingListItem = firstListItem.PreviousListItem;

            if (leadingListItem != null)
            {
                // We have a leading ListItem, so pull selected items into it
                leadingListItem.Reposition(leadingListItem.ContentStart, lastListItem.ElementEnd);
            }
            else
            {
                // We do not have a leading ListItem. So pull selected items out of a list

                // Cut wrapping list after endListItem
                if (lastListItem.NextListItem != null)
                {
                    TextRangeEdit.SplitElement(lastListItem.ElementEnd);
                }

                // Set list to remove
                listToRemove = firstListItem.List;
            }

            // Remove ListItems from all selected blocks
            ListItem listItem = firstListItem;

            while (listItem != null)
            {
                ListItem nextListItem = listItem.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as ListItem;

                // If this is an empty <ListItem></ListItem>, insert an explicit paragraph in it before deleting the list item.
                if (listItem.ContentStart.CompareTo(listItem.ContentEnd) == 0)
                {
                    TextRangeEditTables.EnsureInsertionPosition(listItem.ContentStart);
                }

                listItem.Reposition(null, null);
                listItem = listItem == lastListItem ? null : nextListItem;
            }

            // If we have a list to remove, remove it and set its FlowDirection to its children
            if (listToRemove != null)
            {
                FlowDirection flowDirection = (FlowDirection)listToRemove.GetValue(Paragraph.FlowDirectionProperty);
                listToRemove.Reposition(null, null);
                TextRangeEdit.SetParagraphProperty(range.Start, range.End, Paragraph.FlowDirectionProperty, flowDirection);
            }
        }
示例#10
0
        private static void DecreaseIndentation(TextSelection thisSelection, ListItem parentListItem, ListItem immediateListItem)
        {
            if (immediateListItem != null)
            {
                TextRangeEditLists.UnindentListItems(thisSelection);
            }
            else if (parentListItem != null)
            {
                TextRangeEditLists.ConvertParagraphsToListItems(thisSelection, TextMarkerStyle.Disc);
                TextRangeEditLists.UnindentListItems(thisSelection);
            }
            else
            {
                if (thisSelection.IsEmpty)
                {
                    // When selection is empty, handle indentation based on current TextIndent property of the paragraph.
                    Block paragraphOrBlockUIContainer = thisSelection.Start.ParagraphOrBlockUIContainer;
                    if (paragraphOrBlockUIContainer is BlockUIContainer)
                    {
                        // Decrement BlockUIContainer's leading margin.
                        TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, /*increment:*/ 20, PropertyValueAction.DecreaseByAbsoluteValue);
                    }
                    else
                    {
                        // Create implicit paragraph if at a potential paragraph position, such as empty FlowDocument, TableCell.
                        CreateImplicitParagraphIfNeededAndUpdateSelection(thisSelection);

                        Paragraph paragraph = thisSelection.Start.Paragraph;
                        Invariant.Assert(paragraph != null, "EnsureInsertionPosition must guarantee a position in text content");

                        // When selection is empty, handle indentation based on current TextIndent property of the paragraph.
                        if (paragraph.TextIndent > 20)
                        {
                            // Reset text indent to 20.
                            TextRangeEdit.SetParagraphProperty(thisSelection.Start, thisSelection.End, Paragraph.TextIndentProperty, 20.0, PropertyValueAction.SetValue);
                        }
                        else if (paragraph.TextIndent > 0)
                        {
                            // Reset text indent to 0.
                            TextRangeEdit.SetParagraphProperty(thisSelection.Start, thisSelection.End, Paragraph.TextIndentProperty, 0.0, PropertyValueAction.SetValue);
                        }
                        else
                        {
                            // Decrement paragraph leading margin.
                            TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, /*increment:*/ 20, PropertyValueAction.DecreaseByAbsoluteValue);
                        }
                    }
                }
                else
                {
                    // For non-empty selection, always decrement paragraph margin.
                    TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, /*increment:*/ 20, PropertyValueAction.DecreaseByAbsoluteValue);
                }
            }
        }
        // Token: 0x06003B81 RID: 15233 RVA: 0x0010EEB8 File Offset: 0x0010D0B8
        internal static bool IsListOperationApplicable(TextRange range)
        {
            if (TextRangeEditLists.IsRangeWithinSingleList(range))
            {
                return(true);
            }
            TextPointer textPointer = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);
            Block       paragraphOrBlockUIContainer  = range.Start.ParagraphOrBlockUIContainer;
            Block       paragraphOrBlockUIContainer2 = textPointer.ParagraphOrBlockUIContainer;

            return((paragraphOrBlockUIContainer != null && paragraphOrBlockUIContainer2 != null && paragraphOrBlockUIContainer.Parent == paragraphOrBlockUIContainer2.Parent) || (range.IsEmpty && TextPointerBase.IsAtPotentialParagraphPosition(range.Start)));
        }
 // Token: 0x06003AFF RID: 15103 RVA: 0x0010A8DC File Offset: 0x00108ADC
 internal virtual void ClearAllPropertiesVirtual()
 {
     TextRangeBase.BeginChange(this);
     try
     {
         TextRangeEdit.CharacterResetFormatting(this.Start, this.End);
     }
     finally
     {
         TextRangeBase.EndChange(this);
     }
 }
        // Token: 0x06003B88 RID: 15240 RVA: 0x0010F530 File Offset: 0x0010D730
        internal static bool SplitListsForFlowDirectionChange(TextPointer start, TextPointer end, object newFlowDirectionValue)
        {
            ListItem listAncestor = start.GetListAncestor();

            if (listAncestor != null && listAncestor.List != null && !TextSchema.ValuesAreEqual(newFlowDirectionValue, listAncestor.List.GetValue(Block.FlowDirectionProperty)))
            {
                while (listAncestor != null && listAncestor.List != null && listAncestor.List.Parent is ListItem)
                {
                    if (!TextRangeEditLists.UnindentListItems(new TextRange(start, TextRangeEditLists.GetPositionAfterList(listAncestor.List))))
                    {
                        return(false);
                    }
                    listAncestor = start.GetListAncestor();
                }
            }
            ListItem listItem = end.GetListAncestor();

            if (listItem != null && listItem.List != null && !TextSchema.ValuesAreEqual(newFlowDirectionValue, listItem.List.GetValue(Block.FlowDirectionProperty)))
            {
                if (listAncestor == null || listAncestor.List == null || listItem.List.ElementEnd.CompareTo(listAncestor.List.ElementEnd) >= 0)
                {
                    while (listItem != null && listItem.List != null && listItem.List.Parent is ListItem)
                    {
                        if (!TextRangeEditLists.UnindentListItems(new TextRange(listItem.List.ContentStart, TextRangeEditLists.GetPositionAfterList(listItem.List))))
                        {
                            return(false);
                        }
                        listItem = end.GetListAncestor();
                    }
                }
            }
            if ((listAncestor = start.GetListAncestor()) != null && listAncestor.PreviousListItem != null && listAncestor.List != null && !TextSchema.ValuesAreEqual(newFlowDirectionValue, listAncestor.List.GetValue(Block.FlowDirectionProperty)))
            {
                Invariant.Assert(!(listAncestor.List.Parent is ListItem), "startListItem's list must not be nested!");
                TextRangeEdit.SplitElement(listAncestor.ElementStart);
            }
            if ((listItem = end.GetListAncestor()) != null && listItem.List != null && !TextSchema.ValuesAreEqual(newFlowDirectionValue, listItem.List.GetValue(Block.FlowDirectionProperty)))
            {
                if (listItem.List.Parent is ListItem)
                {
                    while (listItem.List != null && listItem.List.Parent is ListItem)
                    {
                        listItem = (ListItem)listItem.List.Parent;
                    }
                }
                if (listItem.List != null && listItem.NextListItem != null)
                {
                    Invariant.Assert(!(listItem.List.Parent is ListItem), "endListItem's list must not be nested!");
                    TextRangeEdit.SplitElement(listItem.ElementEnd);
                }
            }
            return(true);
        }
示例#14
0
        internal static void IndentListItems(TextRange range)
        {
            ListItem firstListItem = TextPointerBase.GetImmediateListItem(range.Start);
            ListItem lastListItem  = TextPointerBase.GetImmediateListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End));

            // The range must be in a sequence of ListItems belonging to one List wrapper
            if (firstListItem == null || lastListItem == null ||
                firstListItem.Parent != lastListItem.Parent ||
                !(firstListItem.Parent is List))
            {
                return;
            }

            // Identify a ListItem which will become a leading item for this potential sublist
            ListItem leadingListItem = firstListItem.PreviousListItem;

            if (leadingListItem == null)
            {
                // There is no leading list item for this group. Indentation is impossible
                return;
            }

            // Get current List
            List list = (List)firstListItem.Parent;

            // Wrap these items into a List - inheriting all properties from our current list
            List indentedList = (List)TextRangeEdit.InsertElementClone(firstListItem.ElementStart, lastListItem.ElementEnd, list);

            // Wrap the leading ListItem to include the sublist
            leadingListItem.Reposition(leadingListItem.ContentStart, indentedList.ElementEnd);

            // Unwrap sublist from the last selected list item (to keep it on its level)
            Paragraph leadingParagraphOfLastItem = lastListItem.Blocks.FirstBlock as Paragraph;

            if (leadingParagraphOfLastItem != null)
            {
                // Unindenting all items of a sublist - if it is the only following element of a list
                List nestedListOfLastItem = leadingParagraphOfLastItem.NextBlock as List;
                if (nestedListOfLastItem != null && nestedListOfLastItem.NextBlock == null)
                {
                    lastListItem.Reposition(lastListItem.ContentStart, nestedListOfLastItem.ElementStart);
                    nestedListOfLastItem.Reposition(null, null);
                }
            }

            // Merge with neighboring lists
            MergeLists(indentedList.ElementStart);
            // No need in merging at nestedList.ElementEnd as ListItem ends there.
        }
示例#15
0
 // Token: 0x06003546 RID: 13638 RVA: 0x000F1448 File Offset: 0x000EF648
 private TextPointer SplitElement(TextPointer position)
 {
     if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
     {
         position = position.GetNextContextPosition(LogicalDirection.Backward);
     }
     else if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
     {
         position = position.GetNextContextPosition(LogicalDirection.Forward);
     }
     else
     {
         position = TextRangeEdit.SplitElement(position);
     }
     return(position);
 }
        // Token: 0x06003B82 RID: 15234 RVA: 0x0010EF28 File Offset: 0x0010D128
        internal static bool ConvertParagraphsToListItems(TextRange range, TextMarkerStyle markerStyle)
        {
            if (range.IsEmpty && TextPointerBase.IsAtPotentialParagraphPosition(range.Start))
            {
                TextPointer textPointer = TextRangeEditTables.EnsureInsertionPosition(range.Start);
                ((ITextRange)range).Select(textPointer, textPointer);
            }
            Block       paragraphOrBlockUIContainer = range.Start.ParagraphOrBlockUIContainer;
            TextPointer textPointer2 = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);
            Block       paragraphOrBlockUIContainer2 = textPointer2.ParagraphOrBlockUIContainer;

            if (paragraphOrBlockUIContainer == null || paragraphOrBlockUIContainer2 == null || paragraphOrBlockUIContainer.Parent != paragraphOrBlockUIContainer2.Parent || (paragraphOrBlockUIContainer.Parent is ListItem && paragraphOrBlockUIContainer.PreviousBlock == null))
            {
                return(false);
            }
            Block block = paragraphOrBlockUIContainer;

            while (block != paragraphOrBlockUIContainer2 && block != null)
            {
                if (block is Table || block is Section)
                {
                    return(false);
                }
                block = block.NextBlock;
            }
            ListItem listItem = paragraphOrBlockUIContainer.Parent as ListItem;

            if (listItem != null)
            {
                Block block3;
                for (Block block2 = paragraphOrBlockUIContainer; block2 != null; block2 = block3)
                {
                    block3 = ((block2 == paragraphOrBlockUIContainer2) ? null : (block2.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as Block));
                    Invariant.Assert(block2.Parent is ListItem);
                    TextRangeEdit.SplitElement(block2.ElementStart);
                }
            }
            else
            {
                new List
                {
                    MarkerStyle = markerStyle
                }.Apply(paragraphOrBlockUIContainer, paragraphOrBlockUIContainer2);
            }
            return(true);
        }
        // Token: 0x06003B80 RID: 15232 RVA: 0x0010EE34 File Offset: 0x0010D034
        internal static bool MergeLists(TextPointer mergePosition)
        {
            if (mergePosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementEnd || mergePosition.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.ElementStart)
            {
                return(false);
            }
            List list  = mergePosition.GetAdjacentElement(LogicalDirection.Backward) as List;
            List list2 = mergePosition.GetAdjacentElement(LogicalDirection.Forward) as List;

            if (list == null || list2 == null)
            {
                return(false);
            }
            list.Reposition(list.ContentStart, list2.ElementEnd);
            list2.Reposition(null, null);
            TextRangeEdit.SetParagraphProperty(list.ElementStart, list.ElementEnd, Block.FlowDirectionProperty, list.GetValue(Block.FlowDirectionProperty));
            return(true);
        }
示例#18
0
        // Token: 0x060031BA RID: 12730 RVA: 0x000DBC04 File Offset: 0x000D9E04
        internal void Apply(Block firstBlock, Block lastBlock)
        {
            Invariant.Assert(base.Parent == null, "Cannot Apply List Because It Is Inserted In The Tree Already.");
            Invariant.Assert(base.IsEmpty, "Cannot Apply List Because It Is Not Empty.");
            Invariant.Assert(firstBlock.Parent == lastBlock.Parent, "Cannot Apply List Because Block Are Not Siblings.");
            TextContainer textContainer = base.TextContainer;

            textContainer.BeginChange();
            try
            {
                base.Reposition(firstBlock.ElementStart, lastBlock.ElementEnd);
                ListItem listItem;
                for (Block block = firstBlock; block != null; block = ((block == lastBlock) ? null : ((Block)listItem.ElementEnd.GetAdjacentElement(LogicalDirection.Forward))))
                {
                    if (block is List)
                    {
                        listItem = (block.ElementStart.GetAdjacentElement(LogicalDirection.Backward) as ListItem);
                        if (listItem != null)
                        {
                            listItem.Reposition(listItem.ContentStart, block.ElementEnd);
                        }
                        else
                        {
                            listItem = new ListItem();
                            listItem.Reposition(block.ElementStart, block.ElementEnd);
                        }
                    }
                    else
                    {
                        listItem = new ListItem();
                        listItem.Reposition(block.ElementStart, block.ElementEnd);
                        block.ClearValue(Block.MarginProperty);
                        block.ClearValue(Block.PaddingProperty);
                        block.ClearValue(Paragraph.TextIndentProperty);
                    }
                }
                TextRangeEdit.SetParagraphProperty(base.ElementStart, base.ElementEnd, Block.FlowDirectionProperty, firstBlock.GetValue(Block.FlowDirectionProperty));
            }
            finally
            {
                textContainer.EndChange();
            }
        }
        // Token: 0x06003B83 RID: 15235 RVA: 0x0010F058 File Offset: 0x0010D258
        internal static void ConvertListItemsToParagraphs(TextRange range)
        {
            ListItem listItem  = TextPointerBase.GetListItem(range.Start);
            ListItem listItem2 = TextPointerBase.GetListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End));

            if (listItem == null || listItem2 == null || listItem.Parent != listItem2.Parent || !(listItem.Parent is List))
            {
                return;
            }
            List     list             = null;
            ListItem previousListItem = listItem.PreviousListItem;

            if (previousListItem != null)
            {
                previousListItem.Reposition(previousListItem.ContentStart, listItem2.ElementEnd);
            }
            else
            {
                if (listItem2.NextListItem != null)
                {
                    TextRangeEdit.SplitElement(listItem2.ElementEnd);
                }
                list = listItem.List;
            }
            ListItem listItem4;

            for (ListItem listItem3 = listItem; listItem3 != null; listItem3 = ((listItem3 == listItem2) ? null : listItem4))
            {
                listItem4 = (listItem3.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as ListItem);
                if (listItem3.ContentStart.CompareTo(listItem3.ContentEnd) == 0)
                {
                    TextRangeEditTables.EnsureInsertionPosition(listItem3.ContentStart);
                }
                listItem3.Reposition(null, null);
            }
            if (list != null)
            {
                FlowDirection flowDirection = (FlowDirection)list.GetValue(Block.FlowDirectionProperty);
                list.Reposition(null, null);
                TextRangeEdit.SetParagraphProperty(range.Start, range.End, Block.FlowDirectionProperty, flowDirection);
            }
        }
        // Token: 0x06003863 RID: 14435 RVA: 0x000FC504 File Offset: 0x000FA704
        private static bool PasteTextElement(TextEditor This, TextElement sectionOrSpan)
        {
            bool result = false;

            This.Selection.BeginChange();
            try
            {
                ((TextRange)This.Selection).SetXmlVirtual(sectionOrSpan);
                TextRangeEditLists.MergeListsAroundNormalizedPosition((TextPointer)This.Selection.Start);
                TextRangeEditLists.MergeListsAroundNormalizedPosition((TextPointer)This.Selection.End);
                TextRangeEdit.MergeFlowDirection((TextPointer)This.Selection.Start);
                TextRangeEdit.MergeFlowDirection((TextPointer)This.Selection.End);
                result = true;
            }
            finally
            {
                This.Selection.EndChange();
            }
            return(result);
        }
示例#21
0
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        #region Private Methods

        // ................................................................
        //
        // Editing Commands: Character Editing
        //
        // ................................................................

        private static void OnResetFormat(object target, ExecutedRoutedEventArgs args)
        {
            TextEditor This = TextEditor._GetTextEditor(target);

            if (This == null || !This._IsEnabled || This.IsReadOnly || !This.AcceptsRichContent || !(This.Selection.Start is TextPointer))
            {
                return;
            }

            TextEditorTyping._FlushPendingInputItems(This);

            using (This.Selection.DeclareChangeBlock())
            {
                // Positions to clear all inline formatting properties
                TextPointer startResetFormatPosition = (TextPointer)This.Selection.Start;
                TextPointer endResetFormatPosition   = (TextPointer)This.Selection.End;

                if (This.Selection.IsEmpty)
                {
                    TextSegment autoWordRange = TextRangeBase.GetAutoWord(This.Selection);
                    if (autoWordRange.IsNull)
                    {
                        // Clear springloaded formatting
                        ((TextSelection)This.Selection).ClearSpringloadFormatting();
                        return;
                    }
                    else
                    {
                        // If we have a word, apply reset format to it
                        startResetFormatPosition = (TextPointer)autoWordRange.Start;
                        endResetFormatPosition   = (TextPointer)autoWordRange.End;
                    }
                }

                // Forget previously suggested horizontal position
                TextEditorSelection._ClearSuggestedX(This);

                // Clear all inline formattings
                TextRangeEdit.CharacterResetFormatting(startResetFormatPosition, endResetFormatPosition);
            }
        }
        // Token: 0x06003878 RID: 14456 RVA: 0x000FCFC8 File Offset: 0x000FB1C8
        private static void DecreaseIndentation(TextSelection thisSelection, ListItem parentListItem, ListItem immediateListItem)
        {
            if (immediateListItem != null)
            {
                TextRangeEditLists.UnindentListItems(thisSelection);
                return;
            }
            if (parentListItem != null)
            {
                TextRangeEditLists.ConvertParagraphsToListItems(thisSelection, TextMarkerStyle.Disc);
                TextRangeEditLists.UnindentListItems(thisSelection);
                return;
            }
            if (!thisSelection.IsEmpty)
            {
                TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, 20.0, PropertyValueAction.DecreaseByAbsoluteValue);
                return;
            }
            Block paragraphOrBlockUIContainer = thisSelection.Start.ParagraphOrBlockUIContainer;

            if (paragraphOrBlockUIContainer is BlockUIContainer)
            {
                TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, 20.0, PropertyValueAction.DecreaseByAbsoluteValue);
                return;
            }
            TextEditorLists.CreateImplicitParagraphIfNeededAndUpdateSelection(thisSelection);
            Paragraph paragraph = thisSelection.Start.Paragraph;

            Invariant.Assert(paragraph != null, "EnsureInsertionPosition must guarantee a position in text content");
            if (paragraph.TextIndent > 20.0)
            {
                TextRangeEdit.SetParagraphProperty(thisSelection.Start, thisSelection.End, Paragraph.TextIndentProperty, 20.0, PropertyValueAction.SetValue);
                return;
            }
            if (paragraph.TextIndent > 0.0)
            {
                TextRangeEdit.SetParagraphProperty(thisSelection.Start, thisSelection.End, Paragraph.TextIndentProperty, 0.0, PropertyValueAction.SetValue);
                return;
            }
            TextRangeEdit.IncrementParagraphLeadingMargin(thisSelection, 20.0, PropertyValueAction.DecreaseByAbsoluteValue);
        }
        // Token: 0x06003835 RID: 14389 RVA: 0x000FA980 File Offset: 0x000F8B80
        internal static void _OnApplyProperty(TextEditor This, DependencyProperty formattingProperty, object propertyValue, bool applyToParagraphs, PropertyValueAction propertyValueAction)
        {
            if (This == null || !This._IsEnabled || This.IsReadOnly || !This.AcceptsRichContent || !(This.Selection is TextSelection))
            {
                return;
            }
            if (!TextSchema.IsParagraphProperty(formattingProperty) && !TextSchema.IsCharacterProperty(formattingProperty))
            {
                Invariant.Assert(false, "The property '" + formattingProperty.Name + "' is unknown to TextEditor");
                return;
            }
            TextSelection textSelection = (TextSelection)This.Selection;

            if (TextSchema.IsStructuralCharacterProperty(formattingProperty) && !TextRangeEdit.CanApplyStructuralInlineProperty(textSelection.Start, textSelection.End))
            {
                return;
            }
            TextEditorTyping._FlushPendingInputItems(This);
            TextEditorSelection._ClearSuggestedX(This);
            TextEditorTyping._BreakTypingSequence(This);
            textSelection.ApplyPropertyValue(formattingProperty, propertyValue, applyToParagraphs, propertyValueAction);
        }
 // Token: 0x06003AFE RID: 15102 RVA: 0x0010A744 File Offset: 0x00108944
 internal virtual void ApplyPropertyToTextVirtual(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction)
 {
     TextRangeBase.BeginChange(this);
     try
     {
         for (int i = 0; i < this._textSegments.Count; i++)
         {
             TextSegment textSegment = this._textSegments[i];
             if (formattingProperty == FrameworkElement.FlowDirectionProperty)
             {
                 if (applyToParagraphs || this.IsEmpty || TextRangeBase.IsParagraphBoundaryCrossed(this))
                 {
                     TextRangeEdit.SetParagraphProperty((TextPointer)textSegment.Start, (TextPointer)textSegment.End, formattingProperty, value, propertyValueAction);
                 }
                 else
                 {
                     TextRangeEdit.SetInlineProperty((TextPointer)textSegment.Start, (TextPointer)textSegment.End, formattingProperty, value, propertyValueAction);
                 }
             }
             else if (TextSchema.IsCharacterProperty(formattingProperty))
             {
                 TextRangeEdit.SetInlineProperty((TextPointer)textSegment.Start, (TextPointer)textSegment.End, formattingProperty, value, propertyValueAction);
             }
             else if (TextSchema.IsParagraphProperty(formattingProperty))
             {
                 if (formattingProperty.PropertyType == typeof(Thickness) && (FlowDirection)textSegment.Start.GetValue(Block.FlowDirectionProperty) == FlowDirection.RightToLeft)
                 {
                     value = new Thickness(((Thickness)value).Right, ((Thickness)value).Top, ((Thickness)value).Left, ((Thickness)value).Bottom);
                 }
                 TextRangeEdit.SetParagraphProperty((TextPointer)textSegment.Start, (TextPointer)textSegment.End, formattingProperty, value, propertyValueAction);
             }
         }
     }
     finally
     {
         TextRangeBase.EndChange(this);
     }
 }
        // Token: 0x06003B86 RID: 15238 RVA: 0x0010F434 File Offset: 0x0010D634
        private static bool IsRangeWithinSingleList(TextRange range)
        {
            ListItem    listItem    = TextPointerBase.GetListItem(range.Start);
            TextPointer textPointer = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);
            ListItem    listItem2   = TextPointerBase.GetListItem(textPointer);

            if (listItem != null && listItem2 != null && listItem.Parent == listItem2.Parent)
            {
                return(true);
            }
            if (listItem != null && listItem2 != null)
            {
                while (textPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
                {
                    if (textPointer.Parent == listItem.Parent)
                    {
                        return(true);
                    }
                    textPointer = textPointer.GetNextContextPosition(LogicalDirection.Forward);
                }
            }
            return(false);
        }
示例#26
0
        /// <summary>
        /// Inserts a List around a sequence of Blocks
        /// starting from firstBlock ending with lastBlock.
        /// the List must be empty and not inserted in a tree
        /// before the operation
        /// </summary>
        /// <param name="firstBlock"></param>
        /// <param name="lastBlock"></param>
        internal void Apply(Block firstBlock, Block lastBlock)
        {
            Invariant.Assert(this.Parent == null, "Cannot Apply List Because It Is Inserted In The Tree Already.");
            Invariant.Assert(this.IsEmpty, "Cannot Apply List Because It Is Not Empty.");
            Invariant.Assert(firstBlock.Parent == lastBlock.Parent, "Cannot Apply List Because Block Are Not Siblings.");

            TextContainer textContainer = this.TextContainer;

            textContainer.BeginChange();
            try
            {
                // Wrap all block items into this List element
                this.Reposition(firstBlock.ElementStart, lastBlock.ElementEnd);

                // Add ListItem elements
                Block block = firstBlock;
                while (block != null)
                {
                    ListItem listItem;
                    if (block is List)
                    {
                        // To wrap List into list item we pull it into previous ListItem (if any) as sublist
                        listItem = block.ElementStart.GetAdjacentElement(LogicalDirection.Backward) as ListItem;
                        if (listItem != null)
                        {
                            // Wrap the List into preceding ListItem
                            listItem.Reposition(listItem.ContentStart, block.ElementEnd);
                        }
                        else
                        {
                            // No preceding ListItem. Create new one
                            listItem = new ListItem();
                            listItem.Reposition(block.ElementStart, block.ElementEnd);
                        }
                    }
                    else
                    {
                        // To wrap paragraph into list item we need to create a new one
                        //
                        listItem = new ListItem();
                        listItem.Reposition(block.ElementStart, block.ElementEnd);

                        // MS Word-like heuristic: clear margin from a paragraph before wrapping it into a list item
                        // Note: using TextContainer to make sure that undo unit is created.
                        block.ClearValue(Block.MarginProperty);
                        block.ClearValue(Block.PaddingProperty);
                        block.ClearValue(Paragraph.TextIndentProperty);
                    }

                    // Stop when the last paragraph is covered
                    block = block == lastBlock ? null : (Block)listItem.ElementEnd.GetAdjacentElement(LogicalDirection.Forward);
                }

                // We need to set appropriate FlowDirection property on the new List and its paragraph children.
                // We take the FlowDirection value from the first paragraph's FlowDirection value.

                TextRangeEdit.SetParagraphProperty(this.ElementStart, this.ElementEnd,
                                                   Paragraph.FlowDirectionProperty, firstBlock.GetValue(Paragraph.FlowDirectionProperty));
            }
            finally
            {
                textContainer.EndChange();
            }
        }
示例#27
0
        // Checks if start and end positions are parented by a List.
        // If so, unindents list items between (start - start's list end) or (end's list start - end)
        // until they are parented by a top level list.
        // Then, if needed, splits the list(s) at start and/or end positions.
        // Returns false if splitting is not successful due to a failing unindent operation on any nested lists.
        internal static bool SplitListsForFlowDirectionChange(TextPointer start, TextPointer end, object newFlowDirectionValue)
        {
            ListItem startListItem = start.GetListAncestor();

            // Unindent startListItem's list to prepare for a split, if the List's FlowDirection value is different.
            if (startListItem != null &&
                startListItem.List != null && // Check for unparented list items
                !TextSchema.ValuesAreEqual(/*newValue*/ newFlowDirectionValue, /*currentValue*/ startListItem.List.GetValue(Paragraph.FlowDirectionProperty)))
            {
                while (startListItem != null &&
                       startListItem.List != null &&
                       startListItem.List.Parent is ListItem)
                {
                    // startListItem is within a nested List.
                    if (!UnindentListItems(new TextRange(start, GetPositionAfterList(startListItem.List))))
                    {
                        return(false);
                    }
                    startListItem = start.GetListAncestor();
                }
            }

            ListItem endListItem = end.GetListAncestor();

            // Unindent endListItem's list to prepare for a split, if the List's FlowDirection value is different.
            if (endListItem != null &&
                endListItem.List != null &&
                !TextSchema.ValuesAreEqual(/*newValue*/ newFlowDirectionValue, /*currentValue*/ endListItem.List.GetValue(Paragraph.FlowDirectionProperty)))
            {
                if (startListItem != null && startListItem.List != null &&
                    endListItem.List.ElementEnd.CompareTo(startListItem.List.ElementEnd) < 0)
                {
                    // endListItem's List is contained within startListItem's List.
                    // No need to unindent endListItem.
                }
                else
                {
                    while (endListItem != null &&
                           endListItem.List != null &&
                           endListItem.List.Parent is ListItem)
                    {
                        // endListItem is within a nested List.
                        if (!UnindentListItems(new TextRange(endListItem.List.ContentStart, GetPositionAfterList(endListItem.List))))
                        {
                            return(false);
                        }
                        endListItem = end.GetListAncestor();
                    }
                }
            }

            // Split list(s) at boundary position(s) if
            //  1. startListItem is not the first list item within its list (or endListItem is not the last one)
            //  and
            //  2. start/end's parent List's flow direction value is different than the new value being set

            if ((startListItem = start.GetListAncestor()) != null && startListItem.PreviousListItem != null &&
                startListItem.List != null && // Check for unparented list items
                (!TextSchema.ValuesAreEqual(/*newValue*/ newFlowDirectionValue, /*currentValue*/ startListItem.List.GetValue(Paragraph.FlowDirectionProperty))))
            {
                Invariant.Assert(!(startListItem.List.Parent is ListItem), "startListItem's list must not be nested!");
                TextRangeEdit.SplitElement(startListItem.ElementStart);
            }

            if ((endListItem = end.GetListAncestor()) != null &&
                endListItem.List != null && // Check for unparented list items
                (!TextSchema.ValuesAreEqual(/*newValue*/ newFlowDirectionValue, /*currentValue*/ endListItem.List.GetValue(Paragraph.FlowDirectionProperty))))
            {
                // Walk up from endListItem to find the topmost listitem that contains it.
                if (endListItem.List.Parent is ListItem)
                {
                    while (endListItem.List != null && endListItem.List.Parent is ListItem)
                    {
                        endListItem = (ListItem)endListItem.List.Parent;
                    }
                }
                if (endListItem.List != null && endListItem.NextListItem != null)
                {
                    Invariant.Assert(!(endListItem.List.Parent is ListItem), "endListItem's list must not be nested!");
                    TextRangeEdit.SplitElement(endListItem.ElementEnd);
                }
            }

            return(true);
        }
示例#28
0
        internal static bool UnindentListItems(TextRange range)
        {
            // If listitems in this range cross a list boundary, we cannot unindent them.
            if (!IsRangeWithinSingleList(range))
            {
                return(false);
            }

            ListItem firstListItem = TextPointerBase.GetListItem(range.Start);
            ListItem lastListItem  = TextPointerBase.GetListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End));

            // At this point it is possible that lastListItem is a child of
            // firstListItem.
            //
            // This is due to a special case in IsRangeWithinSingleList
            // which allows the input TextRange to cross List boundaries only
            // in the case where the TextRange ends adjacent to an insertion
            // position at the same level as the start, e.g.:
            //
            //    - parent item
            //      - start item (range starts here)
            //          - child item (range ends here)
            //      <start item must not have any siblings>
            //
            // Here we check for that special case and ensure that
            // lastListItem is at the same level as firstListItem.

            TextElement parent = (TextElement)lastListItem.Parent;

            while (parent != firstListItem.Parent)
            {
                lastListItem = parent as ListItem;
                parent       = (TextElement)parent.Parent;
            }
            if (lastListItem == null)
            {
                // This can happen if the input is a fragment, a collection
                // of ListItems not parented by an outer List.
                return(false);
            }

            // Cut wrapping list before startListItem
            if (firstListItem.PreviousListItem != null)
            {
                TextRangeEdit.SplitElement(firstListItem.ElementStart);
            }

            // Cut wrapping list after endListItem
            if (lastListItem.NextListItem != null)
            {
                TextRangeEdit.SplitElement(lastListItem.ElementEnd);
            }

            // Remove List wrapper from selected items
            List unindentedList = (List)firstListItem.Parent;

            // Check whether we have outer ListItem
            ListItem outerListItem = unindentedList.Parent as ListItem;

            if (outerListItem != null)
            {
                // Selected items belong to a nested list.
                // So we need to pull them to the level of enclosing ListItem, i.e. cut this ListItem.
                // In this case we also need to include trailing list into the last of selected items

                // Remove a wrapping List from selected items
                unindentedList.Reposition(null, null);

                // Remember end position of outerListItem to pull any trailing list or other blocks into the last of selected listitems
                TextPointer outerListItemEnd = outerListItem.ContentEnd;

                if (outerListItem.ContentStart.CompareTo(firstListItem.ElementStart) == 0)
                {
                    // There is nothing before first list item; so outer list item would be empty - just delete it
                    outerListItem.Reposition(null, null);
                }
                else
                {
                    // Wrap all stuff preceding firstListItem in outerListItem
                    outerListItem.Reposition(outerListItem.ContentStart, firstListItem.ElementStart);
                }

                if (outerListItemEnd.CompareTo(lastListItem.ElementEnd) == 0)
                {
                    // There are no following siblings to pull into last selected item; do nothing.
                }
                else
                {
                    // Pull trailing items (following siblings to the selected ones) into the last selected item

                    // Remember a position to merge any trailing list after lastListItem
                    TextPointer mergePosition = lastListItem.ContentEnd;

                    // Reposition last selectd ListItem so that it includes trailing list (or other block) as its children
                    lastListItem.Reposition(lastListItem.ContentStart, outerListItemEnd);

                    // Merge any trailing list with a sublist outdented with our listitem
                    MergeLists(mergePosition);
                }
            }
            else
            {
                // Selected items are not in nested list.
                // We need to simply unwrap them and convert to paragraphs

                TextPointer start = unindentedList.ElementStart;
                TextPointer end   = unindentedList.ElementEnd;

                // Save the list's FlowDirection value, to apply later to its children.
                object listFlowDirectionValue = unindentedList.GetValue(Paragraph.FlowDirectionProperty);

                // Remove a wrapping List from selected items
                unindentedList.Reposition(null, null);

                // Remove ListItems from all selected items
                ListItem listItem = firstListItem;
                while (listItem != null)
                {
                    ListItem nextListItem = listItem.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as ListItem;

                    // If this is an empty <ListItem></ListItem>, insert an explicit paragraph in it before deleting the list item.
                    if (listItem.ContentStart.CompareTo(listItem.ContentEnd) == 0)
                    {
                        TextRangeEditTables.EnsureInsertionPosition(listItem.ContentStart);
                    }

                    listItem.Reposition(null, null);
                    listItem = listItem == lastListItem ? null : nextListItem;
                }

                // Apply FlowDirection of the list just deleted to all its children.
                TextRangeEdit.SetParagraphProperty(start, end, Paragraph.FlowDirectionProperty, listFlowDirectionValue);

                // Merge lists on boundaries
                MergeLists(start);
                MergeLists(end);
            }

            return(true);
        }
示例#29
0
        // --------------------------------------------------------------------
        //
        // Internal Methods
        //
        // --------------------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Merges two paragraphs followinng one another.
        /// The content of a second paragraph is moved into the end
        /// of the first one.
        /// </summary>
        /// <param name="firstParagraphOrBlockUIContainer">
        /// First of two merged paragraphs or BlockUIContainer.
        /// </param>
        /// <param name="secondParagraphOrBlockUIContainer">
        /// Second of two mered paragraphs or BlockUIContainer.
        /// </param>
        /// <returns>
        /// true if paragraphs have been merged; false if no actions where made.
        /// </returns>
        internal static bool MergeParagraphs(Block firstParagraphOrBlockUIContainer, Block secondParagraphOrBlockUIContainer)
        {
            if (!ParagraphsAreMergeable(firstParagraphOrBlockUIContainer, secondParagraphOrBlockUIContainer))
            {
                return(false); // Cannot mearge these paragraphs.
            }

            // Store parent list item of a second paragraph -
            // to correct its structure after the merge
            ListItem secondListItem = secondParagraphOrBlockUIContainer.PreviousBlock == null ? secondParagraphOrBlockUIContainer.Parent as ListItem : null;

            if (secondListItem != null && secondListItem.PreviousListItem == null && secondParagraphOrBlockUIContainer.NextBlock is List)
            {
                // The second paragraph is a first list item in some list.
                // It has a sublists in it, so this sublist must be unindented
                // to avoid double bulleted line.
                List sublistOfSecondParagraph = (List)secondParagraphOrBlockUIContainer.NextBlock;
                if (sublistOfSecondParagraph.ElementEnd.CompareTo(secondListItem.ContentEnd) == 0)
                {
                    secondListItem.Reposition(null, null);
                }
                else
                {
                    secondListItem.Reposition(sublistOfSecondParagraph.ElementEnd, secondListItem.ContentEnd);
                }
                // At this point the schema is temporaty broken: the secondParagraph and the sublistOfSecondParagraph have List as a parent
                sublistOfSecondParagraph.Reposition(null, null);
                // The schema is repared as to sublistOfSecondParagraph concern, but still broken for secondParagraph - must be corrected in the following code
            }

            // Move the second paragraph out of its wrappers separating from the first paragraph (if any).
            // We can not use RepositionWithContent because it would destroy
            // all pointers and ranges within a moved paragraph.
            // Instead we reposition elements around the two paragraphs.
            while (secondParagraphOrBlockUIContainer.ElementStart.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
            {
                TextElement parentBlock = (TextElement)secondParagraphOrBlockUIContainer.Parent;
                Invariant.Assert(parentBlock != null);
                Invariant.Assert(TextSchema.AllowsParagraphMerging(parentBlock.GetType()));

                if (secondParagraphOrBlockUIContainer.ElementEnd.CompareTo(parentBlock.ContentEnd) == 0)
                {
                    // Remove ancestor block if it becomes empty
                    parentBlock.Reposition(null, null);
                }
                else
                {
                    // Move ancestor's Start after the end of our paragraph
                    parentBlock.Reposition(secondParagraphOrBlockUIContainer.ElementEnd, parentBlock.ContentEnd);
                }
            }

            // Store a position after the second paragraph where list merging may be needed
            TextPointer positionAfterSecondParagraph = secondParagraphOrBlockUIContainer.ElementEnd.GetFrozenPointer(LogicalDirection.Forward);

            // Move the second paragraph to become an immediate following sibling of the first paragraph
            while (true)
            {
                TextElement previousBlock = secondParagraphOrBlockUIContainer.ElementStart.GetAdjacentElement(LogicalDirection.Backward) as TextElement;
                // Note: We cannot use Block.NextSibling property, because the structure is invalid during this process

                Invariant.Assert(previousBlock != null);

                if (previousBlock is Paragraph || previousBlock is BlockUIContainer)
                {
                    break;
                }

                Invariant.Assert(TextSchema.AllowsParagraphMerging(previousBlock.GetType()));
                previousBlock.Reposition(previousBlock.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);
            }

            // Now that paragraphs are next to each other merge them.

            // If one of paragraphs is empty we will apply special logic - to preserve a formatting from a non-empty one
            if (secondParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                secondParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer.TextRange.IsEmpty)
            {
                firstParagraphOrBlockUIContainer.RepositionWithContent(null);
            }
            else if (firstParagraphOrBlockUIContainer is Paragraph && secondParagraphOrBlockUIContainer is Paragraph)
            {
                // Do reposition magic for merging paragraph content
                // without destroying any pointers positioned in them.
                // Pull the second paragraph into the first one
                Invariant.Assert(firstParagraphOrBlockUIContainer.ElementEnd.CompareTo(secondParagraphOrBlockUIContainer.ElementStart) == 0);
                firstParagraphOrBlockUIContainer.Reposition(firstParagraphOrBlockUIContainer.ContentStart, secondParagraphOrBlockUIContainer.ElementEnd);

                // Store inline merging position
                TextPointer inlineMergingPosition = secondParagraphOrBlockUIContainer.ElementStart;

                // Now we can delete the second paragraph
                secondParagraphOrBlockUIContainer.Reposition(null, null);

                // Merge formatting elements at the point of paragraphs merging
                TextRangeEdit.MergeFormattingInlines(inlineMergingPosition);
            }

            // Merge ListItems wrapping first and second paragraphs.
            ListItem followingListItem = positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart
                ? positionAfterSecondParagraph.GetAdjacentElement(LogicalDirection.Forward) as ListItem : null;

            if (followingListItem != null && followingListItem == secondListItem)
            {
                ListItem precedingListItem = positionAfterSecondParagraph.GetAdjacentElement(LogicalDirection.Backward) as ListItem;
                if (precedingListItem != null)
                {
                    // Merge the second list item with the preceding one
                    Invariant.Assert(positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);
                    Invariant.Assert(positionAfterSecondParagraph.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd);
                    precedingListItem.Reposition(precedingListItem.ContentStart, followingListItem.ElementEnd);
                    followingListItem.Reposition(null, null);
                }
            }

            // Merge lists at merge position
            MergeLists(positionAfterSecondParagraph);

            return(true);
        }
示例#30
0
        internal static bool ConvertParagraphsToListItems(TextRange range, TextMarkerStyle markerStyle)
        {
            if (range.IsEmpty && TextPointerBase.IsAtPotentialParagraphPosition(range.Start))
            {
                TextPointer insertionPosition = TextRangeEditTables.EnsureInsertionPosition(range.Start);
                ((ITextRange)range).Select(insertionPosition, insertionPosition);
            }

            Block firstBlock = range.Start.ParagraphOrBlockUIContainer;

            TextPointer end       = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End);
            Block       lastBlock = end.ParagraphOrBlockUIContainer;

            // We assume that a range contains a sequence of one-level paragraphs.
            // Otherwise the operation is disabled.
            if (firstBlock == null || lastBlock == null || firstBlock.Parent != lastBlock.Parent ||
                firstBlock.Parent is ListItem && firstBlock.PreviousBlock == null)
            {
                // Either the paragraphs belong to different scopes or first of them has a bullet already.
                // We cannot convert them into bulleted lists.
                return(false);
            }

            // Check that all top-level elements of selection are Paragraphs.
            // We do not apply the command to Tables or Sections.
            for (Block block = firstBlock; block != lastBlock && block != null; block = block.NextBlock)
            {
                if (block is Table || block is Section)
                {
                    return(false);
                }
            }

            ListItem parentListItem = firstBlock.Parent as ListItem;

            if (parentListItem != null)
            {
                // Paragraphs are inside of ListItem already.

                // Split a current ListItem before each of selected blocks
                Block block = firstBlock;
                while (block != null)
                {
                    Block nextBlock = block == lastBlock ? null : block.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as Block;

                    Invariant.Assert(block.Parent is ListItem);
                    TextRangeEdit.SplitElement(block.ElementStart);

                    block = nextBlock;
                }
            }
            else
            {
                // Create a list around all paragraphs
                List list = new List();
                list.MarkerStyle = markerStyle;
                list.Apply(firstBlock, lastBlock);

                // Merge with neighboring lists
                //MergeLists(list.ElementEnd);  // start with End to not loose an instance of "list" during merging with the following list
                //MergeLists(list.ElementStart);
            }

            return(true);
        }