// 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); } }
// 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); }
// 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); }
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); }
/// <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); }
// 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); } }
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); }
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. }
// 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); }
// 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); }
//------------------------------------------------------ // // 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); }
/// <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(); } }
// 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); }
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); }
// -------------------------------------------------------------------- // // 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); }
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); }