/// <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(); } }
// 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(); } }
// Helper that swaps the left and right margins of a block element. private static void SwapBlockLeftAndRightMargins(Block block) { object value = block.GetValue(Block.MarginProperty); if (value is Thickness) { if (Paragraph.IsMarginAuto((Thickness)value)) { // Nothing to do for auto thickess } else { // Swap left and right values object newValue = new Thickness( /*left*/((Thickness)value).Right, /*top:*/((Thickness)value).Top, /*right:*/((Thickness)value).Left, /*bottom:*/((Thickness)value).Bottom); SetPropertyValue(block, Block.MarginProperty, value, newValue); } } }
// Helper for SetParagraphProperty -- applies given property value to passed block element. private static void SetPropertyOnParagraphOrBlockUIContainer(DependencyObject parent, Block block, DependencyProperty property, object value, PropertyValueAction propertyValueAction) { // Get the parent flow direction FlowDirection parentFlowDirection; if (parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } else { parentFlowDirection = (FlowDirection)FrameworkElement.FlowDirectionProperty.GetDefaultValue(typeof(FrameworkElement)); } // Some of paragraph operations depend on its flow direction, so get it first. FlowDirection flowDirection = (FlowDirection)block.GetValue(Block.FlowDirectionProperty); // Inspect a property value for this paragraph object currentValue = block.GetValue(property); object newValue = value; // If we're setting a structural property on a Paragraph, we need to preserve // the current value on its children. PreserveBlockContentStructuralProperty(block, property, currentValue, value); if (property.PropertyType == typeof(Thickness)) { // For Margin, Padding, Border - apply the following logic: Invariant.Assert(currentValue is Thickness, "Expecting the currentValue to be of Thinkness type"); Invariant.Assert(newValue is Thickness, "Expecting the newValue to be of Thinkness type"); newValue = ComputeNewThicknessValue((Thickness)currentValue, (Thickness)newValue, parentFlowDirection, flowDirection, propertyValueAction); } else if (property == Paragraph.TextAlignmentProperty) { Invariant.Assert(value is TextAlignment, "Expecting TextAlignment as a value of a Paragraph.TextAlignmentProperty"); // TextAlignment must be reverted for RightToLeft flow direction newValue = ComputeNewTextAlignmentValue((TextAlignment)value, flowDirection); // For BlockUIContainer text alignment must be translated into // HorizontalAlignment of the child embedded object. if (block is BlockUIContainer) { UIElement embeddedElement = ((BlockUIContainer)block).Child; if (embeddedElement != null) { HorizontalAlignment horizontalAlignment = GetHorizontalAlignmentFromTextAlignment((TextAlignment)newValue); // Create an undo unit for property change on embedded framework element. UIElementPropertyUndoUnit.Add(block.TextContainer, embeddedElement, FrameworkElement.HorizontalAlignmentProperty, horizontalAlignment); embeddedElement.SetValue(FrameworkElement.HorizontalAlignmentProperty, horizontalAlignment); } } } else if (currentValue is double) { newValue = GetNewDoubleValue(property, (double)currentValue, (double)newValue, propertyValueAction); } SetPropertyValue(block, property, currentValue, newValue); if (property == Block.FlowDirectionProperty) { // For flow direction command, we also swap Left and Right margins of the paragraph. // This ensures indentation is mirrored correctly. SwapBlockLeftAndRightMargins(block); } }