/// <summary> /// Returns a TextPointer at a new position by a specified symbol /// count. /// </summary> /// <param name="offset"> /// Number of symbols to advance. offset may be negative, in which /// case the TextPointer is moved backwards. /// </param> /// <param name="direction"> /// LogicalDirection desired for a returned TextPointer. /// </param> /// <returns> /// TextPointer located at requested position in case if requested position /// does exist, otherwize returns null. LogicalDirection of the TextPointer /// returned is as specified by a <paramref name="direction"/>. /// </returns> /// <remarks> /// <para>This method, like all other TextPointer methods, defines a symbol /// as one of:</para> /// <para>- 16 bit Unicode character.</para> /// <para>- opening or closing tag of a <see cref="TextElement"/>.</para> /// <para>- the whole <see cref="UIElement"/> as atomic embedded object.</para> /// <para>See examples in <seealso cref="TextPointer.GetPositionAtOffset(int)"/> method with one parameter.</para> /// </remarks> public TextPointer GetPositionAtOffset(int offset, LogicalDirection direction) { TextPointer position = new TextPointer(this, direction); int actualCount = position.MoveByOffset(offset); if (actualCount == offset) { position.Freeze(); return position; } else { return null; } }
// Notify our TextContainer that a typographic property has changed // value on this TextElement. // This has the side effect of invalidating layout. internal void NotifyTypographicPropertyChanged(bool affectsMeasureOrArrange, bool localValueChanged, DependencyProperty property) { if (!this.IsInTree) // No work to do if no one's listening. { return; } TextContainer tree; TextPointer beforeStart; tree = EnsureTextContainer(); // Take note that something layout related has changed. tree.NextLayoutGeneration(); // Notify any external listeners. if (tree.HasListeners) { // Get the position before the start of this element. beforeStart = new TextPointer(tree, _textElementNode, ElementEdge.BeforeStart, LogicalDirection.Forward); beforeStart.Freeze(); // Raise ContentAffected event that spans entire TextElement (from BeforeStart to AfterEnd). tree.BeginChange(); try { tree.BeforeAddChange(); if (localValueChanged) { tree.AddLocalValueChange(); } tree.AddChange(beforeStart, _textElementNode.SymbolCount, _textElementNode.IMECharCount, PrecursorTextChangeType.PropertyModified, property, !affectsMeasureOrArrange); } finally { tree.EndChange(); } } }
/// <summary> /// Returns a TextPointer at the start of line after skipping /// a given number of line starts in forward or backward direction. /// </summary> /// <param name="count"> /// Offset of the destination line. Negative values specify preceding /// lines, zero specifies the current line, positive values specify /// following lines. /// </param> /// <param name="actualCount"> /// The offset of the line moved to. This value may be less than /// requested if the beginning or end of document is encountered. /// </param> /// <returns> /// TextPointer positioned at the begining of a line requested /// (with LogicalDirection set to Forward). /// If there is no sufficient lines in requested direction, /// returns a position at the beginning of a farthest line /// in this direction. In such case out parameter actualCount /// gets a number of lines actually skipped. /// Unlike the other override in this case the returned pointer is never null. /// </returns> /// <remarks> /// If this TextPointer is at an otherwise ambiguous position, exactly /// between two lines, the LogicalDirection property is used to determine /// current position. So a TextPointer with backward LogicalDirection /// is considered to be at the end of line, and calling MoveToLineBoundary(0) /// would reposition it at the start of the preceding line. Making the /// same call with forward LogicalDirection would leave the TextPointer /// positioned where it started -- at the start of the following line. /// </remarks> public TextPointer GetLineStartPosition(int count, out int actualCount) { this.ValidateLayout(); TextPointer position = new TextPointer(this); if (this.HasValidLayout) { actualCount = position.MoveToLineBoundary(count); } else { actualCount = 0; } position.SetLogicalDirection(LogicalDirection.Forward); position.Freeze(); return position; }