// 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); }
// 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); } }
// Token: 0x06003870 RID: 14448 RVA: 0x000FCC00 File Offset: 0x000FAE00 internal static void DecreaseIndentation(TextEditor This) { TextSelection textSelection = (TextSelection)This.Selection; ListItem listItem = TextPointerBase.GetListItem(textSelection.Start); ListItem immediateListItem = TextPointerBase.GetImmediateListItem(textSelection.Start); TextEditorLists.DecreaseIndentation(textSelection, listItem, immediateListItem); }
// Common handler for all list editing commands private static void OnListCommand(object target, ExecutedRoutedEventArgs args) { TextEditor This = TextEditor._GetTextEditor(target); if (This == null || !This._IsEnabled || This.IsReadOnly || !This.AcceptsRichContent || !(This.Selection is TextSelection)) { return; } TextEditorTyping._FlushPendingInputItems(This); if (!TextRangeEditLists.IsListOperationApplicable((TextSelection)This.Selection)) { return; } using (This.Selection.DeclareChangeBlock()) { TextSelection thisSelection = (TextSelection)This.Selection; ListItem parentListItem = TextPointerBase.GetListItem(thisSelection.Start); ListItem immediateListItem = TextPointerBase.GetImmediateListItem(thisSelection.Start); List list = parentListItem == null ? null : (List)parentListItem.Parent; // Forget previously suggested horizontal position TextEditorSelection._ClearSuggestedX(This); // Execute the command if (args.Command == EditingCommands.ToggleBullets) { ToggleBullets(thisSelection, parentListItem, immediateListItem, list); } else if (args.Command == EditingCommands.ToggleNumbering) { ToggleNumbering(thisSelection, parentListItem, immediateListItem, list); } else if (args.Command == EditingCommands.RemoveListMarkers) { TextRangeEditLists.ConvertListItemsToParagraphs(thisSelection); } else if (args.Command == EditingCommands.IncreaseIndentation) { IncreaseIndentation(thisSelection, parentListItem, immediateListItem); } else if (args.Command == EditingCommands.DecreaseIndentation) { DecreaseIndentation(thisSelection, parentListItem, immediateListItem); } else { Invariant.Assert(false); } } }
// Token: 0x06003874 RID: 14452 RVA: 0x000FCCBC File Offset: 0x000FAEBC private static void OnListCommand(object target, ExecutedRoutedEventArgs args) { TextEditor textEditor = TextEditor._GetTextEditor(target); if (textEditor == null || !textEditor._IsEnabled || textEditor.IsReadOnly || !textEditor.AcceptsRichContent || !(textEditor.Selection is TextSelection)) { return; } TextEditorTyping._FlushPendingInputItems(textEditor); if (!TextRangeEditLists.IsListOperationApplicable((TextSelection)textEditor.Selection)) { return; } using (textEditor.Selection.DeclareChangeBlock()) { TextSelection textSelection = (TextSelection)textEditor.Selection; ListItem listItem = TextPointerBase.GetListItem(textSelection.Start); ListItem immediateListItem = TextPointerBase.GetImmediateListItem(textSelection.Start); List list = (listItem == null) ? null : ((List)listItem.Parent); TextEditorSelection._ClearSuggestedX(textEditor); if (args.Command == EditingCommands.ToggleBullets) { TextEditorLists.ToggleBullets(textSelection, listItem, immediateListItem, list); } else if (args.Command == EditingCommands.ToggleNumbering) { TextEditorLists.ToggleNumbering(textSelection, listItem, immediateListItem, list); } else if (args.Command == EditingCommands.RemoveListMarkers) { TextRangeEditLists.ConvertListItemsToParagraphs(textSelection); } else if (args.Command == EditingCommands.IncreaseIndentation) { TextEditorLists.IncreaseIndentation(textSelection, listItem, immediateListItem); } else if (args.Command == EditingCommands.DecreaseIndentation) { TextEditorLists.DecreaseIndentation(textSelection, listItem, immediateListItem); } else { Invariant.Assert(false); } } }
// 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: 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); }
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); }
// Token: 0x06003B85 RID: 15237 RVA: 0x0010F26C File Offset: 0x0010D46C internal static bool UnindentListItems(TextRange range) { if (!TextRangeEditLists.IsRangeWithinSingleList(range)) { return(false); } ListItem listItem = TextPointerBase.GetListItem(range.Start); ListItem listItem2 = TextPointerBase.GetListItem((TextPointer)TextRangeEdit.GetAdjustedRangeEnd(range.Start, range.End)); for (TextElement textElement = (TextElement)listItem2.Parent; textElement != listItem.Parent; textElement = (TextElement)textElement.Parent) { listItem2 = (textElement as ListItem); } if (listItem2 == null) { return(false); } if (listItem.PreviousListItem != null) { TextRangeEdit.SplitElement(listItem.ElementStart); } if (listItem2.NextListItem != null) { TextRangeEdit.SplitElement(listItem2.ElementEnd); } List list = (List)listItem.Parent; ListItem listItem3 = list.Parent as ListItem; if (listItem3 != null) { list.Reposition(null, null); TextPointer contentEnd = listItem3.ContentEnd; if (listItem3.ContentStart.CompareTo(listItem.ElementStart) == 0) { listItem3.Reposition(null, null); } else { listItem3.Reposition(listItem3.ContentStart, listItem.ElementStart); } if (contentEnd.CompareTo(listItem2.ElementEnd) != 0) { TextPointer contentEnd2 = listItem2.ContentEnd; listItem2.Reposition(listItem2.ContentStart, contentEnd); TextRangeEditLists.MergeLists(contentEnd2); } } else { TextPointer elementStart = list.ElementStart; TextPointer elementEnd = list.ElementEnd; object value = list.GetValue(Block.FlowDirectionProperty); list.Reposition(null, null); ListItem listItem5; for (ListItem listItem4 = listItem; listItem4 != null; listItem4 = ((listItem4 == listItem2) ? null : listItem5)) { listItem5 = (listItem4.ElementEnd.GetAdjacentElement(LogicalDirection.Forward) as ListItem); if (listItem4.ContentStart.CompareTo(listItem4.ContentEnd) == 0) { TextRangeEditTables.EnsureInsertionPosition(listItem4.ContentStart); } listItem4.Reposition(null, null); } TextRangeEdit.SetParagraphProperty(elementStart, elementEnd, Block.FlowDirectionProperty, value); TextRangeEditLists.MergeLists(elementStart); TextRangeEditLists.MergeLists(elementEnd); } return(true); }