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); }
/// <summary> /// Applies a formatting property to this TextRange. /// </summary> /// <param name="formattingProperty"> /// Property to apply. /// </param> /// <param name="value"> /// Specifies a value for the property. /// </param> /// <param name="applyToParagraphs"> /// This parameter is used to resolve the ambiguity for overlapping inherited properties /// that apply to both inline and paragraph elements. /// </param> /// <param name="propertyValueAction"> /// Specifies how to apply the given value - use it for setting, /// for increasing or for decreasing existing values. /// This parameter must have PropertyValueAction.SetValue for all properties that /// cannot be incremented or decremented by their type. /// </param> internal void ApplyPropertyValue(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction) { Invariant.Assert(this.HasConcreteTextContainer, "Can't apply property to non-TextContainer range!"); if (formattingProperty == null) { throw new ArgumentNullException("formattingProperty"); } if (!TextSchema.IsCharacterProperty(formattingProperty) && !TextSchema.IsParagraphProperty(formattingProperty)) { #pragma warning suppress 6506 // formattingProperty is obviously not null throw new ArgumentException(SR.Get(SRID.TextEditorPropertyIsNotApplicableForTextFormatting, formattingProperty.Name)); } // Convert property value from a string to object if needed if ((value is string) && formattingProperty.PropertyType != typeof(string)) { System.ComponentModel.TypeConverter typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(formattingProperty.PropertyType); Invariant.Assert(typeConverter != null); value = typeConverter.ConvertFromString((string)value); } // Check if the value is appropriate for the property if (!formattingProperty.IsValidValue(value) && !(formattingProperty.PropertyType == typeof(Thickness) && (value is Thickness))) { // We exclude checking thcickness values because we have special treatment for negative values // in TextRangeEdit.SetParagraphProperty - negative values mean: "leave the value as is". throw new ArgumentException(SR.Get(SRID.TextEditorTypeOfParameterIsNotAppropriateForFormattingProperty, value == null ? "null" : value.GetType().Name, formattingProperty.Name), "value"); } // Check propertyValueAction validity if (propertyValueAction != PropertyValueAction.SetValue && propertyValueAction != PropertyValueAction.IncreaseByAbsoluteValue && propertyValueAction != PropertyValueAction.DecreaseByAbsoluteValue && propertyValueAction != PropertyValueAction.IncreaseByPercentageValue && propertyValueAction != PropertyValueAction.DecreaseByPercentageValue) { throw new ArgumentException(SR.Get(SRID.TextRange_InvalidParameterValue), "propertyValueAction"); } // Check if propertyValueAction is applicable to this property if (propertyValueAction != PropertyValueAction.SetValue && !TextSchema.IsPropertyIncremental(formattingProperty)) { throw new ArgumentException(SR.Get(SRID.TextRange_PropertyCannotBeIncrementedOrDecremented, formattingProperty.Name), "propertyValueAction"); } ApplyPropertyToTextVirtual(formattingProperty, value, applyToParagraphs, propertyValueAction); }
// Worker for ApplyProperty; enables extensibility for TextSelection internal virtual void ApplyPropertyToTextVirtual(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction) { TextRangeBase.BeginChange(this); try { for (int i = 0; i < _textSegments.Count; i++) { TextSegment textSegment = _textSegments[i]; if (formattingProperty == FrameworkElement.FlowDirectionProperty) { // FlowDirection is an overlapping inheritable property that needs special handling. // We apply it as a paragraph property when: // 1. applyToParagraphs = true or // 2. range is empty or // 3. range crossed paragraph boundary // Otherwise, apply as inline property. 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)) { // We must check for paragraph properties after character ones, // to account for overlapping inheritable properties. // Thinkness properties (Margin, Padding, BorderThickness) have special treatment // in SetParagraphProperty method: it swaps Left and Right values for paragraphs // with RightToLeft flow direction. So we need to set them appropriatly - // depending on the FlowDirection of the first paragraph. if (formattingProperty.PropertyType == typeof(Thickness) && (FlowDirection)textSegment.Start.GetValue(Paragraph.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); } }
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); }
// 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); } }
// Worker for SetParagraphProperty, iterates over Blocks recursively. private static void SetParagraphPropertyWorker(TextPointer start, TextPointer end, DependencyProperty property, object value, PropertyValueAction propertyValueAction) { Block block = GetNextBlock(start, end); while (block != null) { if (TextSchema.IsParagraphOrBlockUIContainer(block.GetType())) { // Get the parent to check the parent FlowDirection with current DependencyObject parent = start.TextContainer.Parent; SetPropertyOnParagraphOrBlockUIContainer(parent, block, property, value, propertyValueAction); // Go to paragraph/BUIC end position, normalize forward start = block.ElementEnd.GetPositionAtOffset(0, LogicalDirection.Forward); } else if (block is List) { // Apply property value to content first, recursively, since // (potentially) setting FlowDirection on the parent List will // affect child elements. TextPointer contentStart = block.ContentStart.GetPositionAtOffset(0, LogicalDirection.Forward); // Normalize forward; contentStart = contentStart.GetNextContextPosition(LogicalDirection.Forward); // Leave scope of initial List. TextPointer contentEnd = block.ContentEnd; SetParagraphPropertyWorker(contentStart, contentEnd, property, value, propertyValueAction); // Special cases for applying paragraph properties to Lists if (property == Block.FlowDirectionProperty) { // Set FlowDirection property on List SetPropertyValue(block, property, /*currentValue:*/block.GetValue(property), /*newValue:*/value); // For flow direction command, we also swap Left and Right margins of the list. // This ensures indentation is mirrored correctly. SwapBlockLeftAndRightMargins(block); } // Go to end position, normalize forward. start = block.ElementEnd.GetPositionAtOffset(0, LogicalDirection.Forward); } block = GetNextBlock(start, end); } }
/// <summary> /// Applies formatting properties for whole block elements. /// </summary> /// <param name="start"> /// a position within first block in sequence /// </param> /// <param name="end"> /// a positionn within last block in sequence /// </param> /// <param name="property"> /// property changed on blocks /// </param> /// <param name="value"> /// value for the property /// </param> /// <param name="propertyValueAction"> /// Specifies how to use the value - as absolute, as increment or a decrement. /// </param> internal static void SetParagraphProperty(TextPointer start, TextPointer end, DependencyProperty property, object value, PropertyValueAction propertyValueAction) { Invariant.Assert(start != null, "null check: start"); Invariant.Assert(end != null, "null check: end"); Invariant.Assert(start.CompareTo(end) <= 0, "expecting: start <= end"); Invariant.Assert(property != null, "null check: property"); // Exclude last opening tag to avoid affecting a paragraph following the selection end = (TextPointer)TextRangeEdit.GetAdjustedRangeEnd(start, end); // Expand start pointer to the beginning of the first paragraph/blockuicontainer Block startParagraphOrBlockUIContainer = start.ParagraphOrBlockUIContainer; if (startParagraphOrBlockUIContainer != null) { start = startParagraphOrBlockUIContainer.ContentStart; } // Applying FlowDirection requires splitting all containing lists on the range boundaries // because the property is applied to whole List element (to affect bullet appearence) if (property == Block.FlowDirectionProperty) { // Split any boundary lists if needed. // We want to maintain the invariant that all lists and paragraphs within a list, have the same FlowDirection value. // If paragraph FlowDirection command requests a different value of FlowDirection on parts of a list, // we split the list to maintain this invariant. if (!TextRangeEditLists.SplitListsForFlowDirectionChange(start, end, value)) { // If lists at start and end cannot be split successfully, we cannot apply FlowDirection property to the paragraph content. return; } // And expand range start to the beginning of the containing list ListItem listItem = start.GetListAncestor(); if (listItem != null && listItem.List != null) { start = listItem.List.ElementStart; } } // Walk all paragraphs in the affected segment. For FlowDirection property, also walk lists. SetParagraphPropertyWorker(start, end, property, value, 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); } }
// Helper to calculate new value of Run.FontSize property when PropertyValueAction is increment/decrement. private static double GetNewFontSizeValue(double currentValue, double value, PropertyValueAction propertyValueAction) { double newValue = value; // Calculate the new value as increment/decrement from the current value if (propertyValueAction == PropertyValueAction.IncreaseByAbsoluteValue) { newValue = currentValue + value; } else if (propertyValueAction == PropertyValueAction.DecreaseByAbsoluteValue) { newValue = currentValue - value; } // Check limiting boundaries if (newValue < TextEditorCharacters.OneFontPoint) { newValue = TextEditorCharacters.OneFontPoint; } else if (newValue > TextEditorCharacters.MaxFontPoint) { newValue = TextEditorCharacters.MaxFontPoint; } return newValue; }
// Helper to set non-structural Inline property to a range between start and end positions. private static void SetNonStructuralInlineProperty(TextPointer start, TextPointer end, DependencyProperty formattingProperty, object value, PropertyValueAction propertyValueAction) { // Split formatting elements at range boundaries start = SplitFormattingElements(start, /*keepEmptyFormatting:*/false, /*preserveStructuralFormatting*/true, /*limitingAncestor*/null); end = SplitFormattingElements(end, /*keepEmptyFormatting:*/false, /*preserveStructuralFormatting*/true, /*limitingAncestor*/null); Run run = TextRangeEdit.GetNextRun(start, end); while (run != null) { object currentValue = run.GetValue(formattingProperty); object newValue = value; if (propertyValueAction != PropertyValueAction.SetValue) { Invariant.Assert(formattingProperty == TextElement.FontSizeProperty, "Only FontSize can be incremented/decremented among character properties"); newValue = GetNewFontSizeValue((double)currentValue, (double)value, propertyValueAction); } // Set new property value SetPropertyValue(run, formattingProperty, currentValue, newValue); // Remember a position after the current run for the following processing. // Normalize forward since Run.ElementEnd has backward gravity. TextPointer nextRunPosition = run.ElementEnd.GetPositionAtOffset(0, LogicalDirection.Forward); if (TextPointerBase.IsAtPotentialRunPosition(run)) { // If current run was an implicit run, we move to the next context position after its element end. // This is safe because by definition of IsAtPotentialRunPosition predicate, // our current run can never have an adjacent run element or // another adjacent potential run position. nextRunPosition = nextRunPosition.GetNextContextPosition(LogicalDirection.Forward); } // Merge this run with the previous one. // Note that this can affect text structure even after this run. MergeFormattingInlines(run.ContentStart); // Find the next Run to process run = TextRangeEdit.GetNextRun(nextRunPosition, end); } MergeFormattingInlines(end); }
// ..................................................................... // // Paragraph Editing Commands // // ..................................................................... /// <summary> /// Increments/decrements paragraph leading maring property. /// For LeftToRight paragraphs a leading maring is the left marinng, /// for RightToLeft paragraphs it is the right maring. /// </summary> /// <param name="range"></param> /// <param name="increment"></param> /// <param name="propertyValueAction"> /// Must be one of IncreaseValue or DecreaseValue. /// </param> internal static void IncrementParagraphLeadingMargin(TextRange range, double increment, PropertyValueAction propertyValueAction) { Invariant.Assert(increment >= 0); Invariant.Assert(propertyValueAction != PropertyValueAction.SetValue); if (increment == 0) { // Nothing to do. Just return. return; } // Note that SetParagraphProperty method will swap Left and Right margins for RightToLeft paragraphs. // Note that -1 values for Thickness axis means leaving its value as is. Thickness thickness = new Thickness(increment, -1, -1, -1); // Apply paragraph margin property TextRangeEdit.SetParagraphProperty(range.Start, range.End, Block.MarginProperty, thickness, propertyValueAction); }
// Applies newValue to the currentValue according to a propertyValueAction - // increments or just sets it. private static double NewValue(double currentValue, double newValue, PropertyValueAction propertyValueAction) { if (double.IsNaN(newValue)) { return newValue; } if (double.IsNaN(currentValue)) { currentValue = 0.0; } newValue = propertyValueAction == PropertyValueAction.IncreaseByAbsoluteValue ? currentValue + newValue : propertyValueAction == PropertyValueAction.DecreaseByAbsoluteValue ? currentValue - newValue : propertyValueAction == PropertyValueAction.IncreaseByPercentageValue ? currentValue * (1.0 + newValue / 100) : propertyValueAction == PropertyValueAction.DecreaseByPercentageValue ? currentValue * (1.0 - newValue / 100) : newValue; return newValue; }
/// <summary> /// Calculates valid value for specified DP, current and new (desired) value, /// and <see cref="PropertyValueAction"/>. /// The value is made to adhere editor's acceptable range of values for given property. /// If the value is invalid, then closest valid bound of the range is returned. /// </summary> /// <param name="property"></param> /// <param name="currentValue"></param> /// <param name="newValue"></param> /// <param name="propertyValueAction"></param> /// <returns>new value</returns> private static double GetNewDoubleValue(DependencyProperty property, double currentValue, double newValue, PropertyValueAction propertyValueAction) { double outValue = NewValue(currentValue, newValue, propertyValueAction); return DoublePropertyBounds.GetClosestValidValue(property, outValue); }
// Helper for SetParagraphProperty private static Thickness ComputeNewThicknessValue(Thickness currentThickness, Thickness newThickness, FlowDirection parentFlowDirection, FlowDirection flowDirection, PropertyValueAction propertyValueAction) { // Negative value for particular axis means "leave it unchanged" double topMargin = newThickness.Top < 0 ? currentThickness.Top : GetNewDoubleValue(null, currentThickness.Top, newThickness.Top, propertyValueAction); double bottomMargin = newThickness.Bottom < 0 ? currentThickness.Bottom : GetNewDoubleValue(null, currentThickness.Bottom, newThickness.Bottom, propertyValueAction); double leftMargin; double rightMargin; if (parentFlowDirection != flowDirection) { // In case of mismatching FlowDirection between parent and current, // we apply value.Left to currentValue.Right and vice versa. // The caller of the method must account for that and use Left/Right margins appropriately. leftMargin = newThickness.Right < 0 ? currentThickness.Left : GetNewDoubleValue(null, currentThickness.Left, newThickness.Right, propertyValueAction); rightMargin = newThickness.Left < 0 ? currentThickness.Right : GetNewDoubleValue(null, currentThickness.Right, newThickness.Left, propertyValueAction); } else { leftMargin = newThickness.Left < 0 ? currentThickness.Left : GetNewDoubleValue(null, currentThickness.Left, newThickness.Left, propertyValueAction); rightMargin = newThickness.Right < 0 ? currentThickness.Right : GetNewDoubleValue(null, currentThickness.Right, newThickness.Right, propertyValueAction); } return new Thickness(leftMargin, topMargin, rightMargin, bottomMargin); }
// 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); }
/// <summary> /// Applies a property value to a selection. /// In case of empty selection sets property to springloaded property set. /// </summary> internal override void ApplyPropertyToTextVirtual(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction) { if (!TextSchema.IsParagraphProperty(formattingProperty) && !TextSchema.IsCharacterProperty(formattingProperty)) { return; // Ignore any unknown property } // Check whether we are in a situation when auto-word formatting must happen if (this.IsEmpty && TextSchema.IsCharacterProperty(formattingProperty) && !applyToParagraphs && formattingProperty != FrameworkElement.FlowDirectionProperty) // We dont want to apply flowdirection property to inlines when selection is empty. { TextSegment autoWordRange = TextRangeBase.GetAutoWord(this); if (autoWordRange.IsNull) { // This property goes to springload formatting. We should not create undo unit for it. if (_springloadFormatting == null) { _springloadFormatting = new DependencyObject(); } _springloadFormatting.SetValue(formattingProperty, value); } else { // TextRange will create undo unit with proper name new TextRange(autoWordRange.Start, autoWordRange.End).ApplyPropertyValue(formattingProperty, value); } } else { // No word to auto-format. Apply property to a selection. // TextRange will create undo unit with proper name base.ApplyPropertyToTextVirtual(formattingProperty, value, applyToParagraphs, propertyValueAction); this.ClearSpringloadFormatting(); } }
/// <summary> /// Applies a property to a range between start and end positions. /// </summary> /// <param name="start"> /// TextPointer identifying start of affected range. /// </param> /// <param name="end"> /// TextPointer identifying end of affected range. /// </param> /// <param name="formattingProperty"> /// A dependency property whose value is supposed to applied to a range. /// </param> /// <param name="value"> /// A value for a property to apply. /// </param> /// <param name="propertyValueAction"> /// Specifies how to use the value - as absolute, as increment or a decrement. /// </param> internal static void SetInlineProperty(TextPointer start, TextPointer end, DependencyProperty formattingProperty, object value, PropertyValueAction propertyValueAction) { // Check for corner case when we have siple text run with all properties set as requested. // This case is iportant optimization for Backspace-Type scenario, when Springload formatting applies for nothing for 50 properties if (start.CompareTo(end) >= 0 || propertyValueAction == PropertyValueAction.SetValue && start.Parent is Run && start.Parent == end.Parent && TextSchema.ValuesAreEqual(start.Parent.GetValue(formattingProperty), value)) { return; } // Remove unnecessary spans on range ends - to optimize resulting markup RemoveUnnecessarySpans(start); RemoveUnnecessarySpans(end); if (TextSchema.IsStructuralCharacterProperty(formattingProperty)) { SetStructuralInlineProperty(start, end, formattingProperty, value); } else { SetNonStructuralInlineProperty(start, end, formattingProperty, value, propertyValueAction); } }
// Token: 0x06003AD7 RID: 15063 RVA: 0x0010A16C File Offset: 0x0010836C internal void ApplyPropertyValue(DependencyProperty formattingProperty, object value, bool applyToParagraphs, PropertyValueAction propertyValueAction) { Invariant.Assert(this.HasConcreteTextContainer, "Can't apply property to non-TextContainer range!"); if (formattingProperty == null) { throw new ArgumentNullException("formattingProperty"); } if (!TextSchema.IsCharacterProperty(formattingProperty) && !TextSchema.IsParagraphProperty(formattingProperty)) { throw new ArgumentException(SR.Get("TextEditorPropertyIsNotApplicableForTextFormatting", new object[] { formattingProperty.Name })); } if (value is string && formattingProperty.PropertyType != typeof(string)) { TypeConverter converter = TypeDescriptor.GetConverter(formattingProperty.PropertyType); Invariant.Assert(converter != null); value = converter.ConvertFromString((string)value); } if (!formattingProperty.IsValidValue(value) && (!(formattingProperty.PropertyType == typeof(Thickness)) || !(value is Thickness))) { throw new ArgumentException(SR.Get("TextEditorTypeOfParameterIsNotAppropriateForFormattingProperty", new object[] { (value == null) ? "null" : value.GetType().Name, formattingProperty.Name }), "value"); } if (propertyValueAction != PropertyValueAction.SetValue && propertyValueAction != PropertyValueAction.IncreaseByAbsoluteValue && propertyValueAction != PropertyValueAction.DecreaseByAbsoluteValue && propertyValueAction != PropertyValueAction.IncreaseByPercentageValue && propertyValueAction != PropertyValueAction.DecreaseByPercentageValue) { throw new ArgumentException(SR.Get("TextRange_InvalidParameterValue"), "propertyValueAction"); } if (propertyValueAction != PropertyValueAction.SetValue && !TextSchema.IsPropertyIncremental(formattingProperty)) { throw new ArgumentException(SR.Get("TextRange_PropertyCannotBeIncrementedOrDecremented", new object[] { formattingProperty.Name }), "propertyValueAction"); } this.ApplyPropertyToTextVirtual(formattingProperty, value, applyToParagraphs, propertyValueAction); }