/// <summary> /// Retrieves the visible ranges of text. /// </summary> /// <returns>The ranges of text that are visible, or possibly an empty array if there is /// no visible text whatsoever. Text in the range may still be obscured by an overlapping /// window. Also, portions /// of the range at the beginning, in the middle, or at the end may not be visible /// because they are scrolled off to the side. /// Providers should ensure they return at most a range from the beginning of the first /// line with portions visible through the end of the last line with portions visible.</returns> ITextRangeProvider[] ITextProvider.GetVisibleRanges() { ITextRangeProvider[] ranges = null; ITextView textView = GetUpdatedTextView(); if (textView != null) { List <TextSegment> visibleTextSegments = new List <TextSegment>(); // Get visible portion of the document. // if (textView is MultiPageTextView) { // For MultiPageTextView assume that all current pages are entirely visible. visibleTextSegments.AddRange(textView.TextSegments); } else { // For all others TextViews get visible rectangle and hittest TopLeft and // BottomRight points to retrieve visible range. // Find out the bounds of the area visible through all nested scroll areas Rect visibleRect = GetVisibleRectangle(textView); if (!visibleRect.IsEmpty) { ITextPointer visibleStart = textView.GetTextPositionFromPoint(visibleRect.TopLeft, true); ITextPointer visibleEnd = textView.GetTextPositionFromPoint(visibleRect.BottomRight, true); visibleTextSegments.Add(new TextSegment(visibleStart, visibleEnd, true)); } } // Create collection of TextRangeProviders for visible ranges. if (visibleTextSegments.Count > 0) { ranges = new ITextRangeProvider[visibleTextSegments.Count]; for (int i = 0; i < visibleTextSegments.Count; i++) { ranges[i] = new TextRangeAdaptor(this, visibleTextSegments[i].Start, visibleTextSegments[i].End, _textPeer); } } } // If no text is visible in the control, return the degenerate text range // (empty range) at the beginning of the document. if (ranges == null) { ranges = new ITextRangeProvider[] { new TextRangeAdaptor(this, _textContainer.Start, _textContainer.Start, _textPeer) }; } return(ranges); }
// Token: 0x060065D2 RID: 26066 RVA: 0x001C8A94 File Offset: 0x001C6C94 ITextRangeProvider ITextProvider.RangeFromPoint(Point location) { TextRangeAdaptor textRangeAdaptor = null; ITextView updatedTextView = this.GetUpdatedTextView(); if (updatedTextView != null) { location = this.ScreenToClient(location, updatedTextView.RenderScope); ITextPointer textPositionFromPoint = updatedTextView.GetTextPositionFromPoint(location, true); if (textPositionFromPoint != null) { textRangeAdaptor = new TextRangeAdaptor(this, textPositionFromPoint, textPositionFromPoint, this._textPeer); } } if (textRangeAdaptor == null) { throw new ArgumentException(SR.Get("TextProvider_InvalidPoint")); } return(textRangeAdaptor); }
/// <summary> /// Finds the degenerate range nearest to a screen coordinate. /// </summary> /// <param name="location">The location in screen coordinates. /// The provider should check that the coordinates are within the client /// area of the provider, and should throw an InvalidOperation exception /// if they are not.</param> /// <returns>A degenerate range nearest the specified location.</returns> ITextRangeProvider ITextProvider.RangeFromPoint(Point location) { TextRangeAdaptor range = null; ITextView textView = GetUpdatedTextView(); if (textView != null) { // Convert the screen point to the element space coordinates. location = ScreenToClient(location, textView.RenderScope); ITextPointer position = textView.GetTextPositionFromPoint(location, true); if (position != null) { range = new TextRangeAdaptor(this, position, position, _textPeer); } } if (range == null) { throw new ArgumentException(SR.Get(SRID.TextProvider_InvalidPoint)); } return(range); }
// Token: 0x060065D0 RID: 26064 RVA: 0x001C8810 File Offset: 0x001C6A10 ITextRangeProvider[] ITextProvider.GetVisibleRanges() { ITextRangeProvider[] array = null; ITextView updatedTextView = this.GetUpdatedTextView(); if (updatedTextView != null) { List <TextSegment> list = new List <TextSegment>(); if (updatedTextView is MultiPageTextView) { list.AddRange(updatedTextView.TextSegments); } else { Rect visibleRectangle = this.GetVisibleRectangle(updatedTextView); if (!visibleRectangle.IsEmpty) { ITextPointer textPositionFromPoint = updatedTextView.GetTextPositionFromPoint(visibleRectangle.TopLeft, true); ITextPointer textPositionFromPoint2 = updatedTextView.GetTextPositionFromPoint(visibleRectangle.BottomRight, true); list.Add(new TextSegment(textPositionFromPoint, textPositionFromPoint2, true)); } } if (list.Count > 0) { array = new ITextRangeProvider[list.Count]; for (int i = 0; i < list.Count; i++) { array[i] = new TextRangeAdaptor(this, list[i].Start, list[i].End, this._textPeer); } } } if (array == null) { array = new ITextRangeProvider[] { new TextRangeAdaptor(this, this._textContainer.Start, this._textContainer.Start, this._textPeer) }; } return(array); }
//------------------------------------------------------------------- // // Internal Methods // //------------------------------------------------------------------- #region Internal Methods /// <summary> /// Retrieves the bounding rectangles for the text lines of a given range. /// </summary> /// <param name="start">Start of range to measure</param> /// <param name="end">End of range to measure</param> /// <param name="clipToView">Specifies whether the caller wants the full bounds (false) or the bounds of visible portions /// of the viewable line only ('true')</param> /// <param name="transformToScreen">Requests the results in screen coordinates</param> /// <returns>An array of bounding rectangles for each line or portion of a line within the client area of the text provider. /// No bounding rectangles will be returned for lines that are empty or scrolled out of view. Note that even though a /// bounding rectangle is returned the corresponding text may not be visible due to overlapping windows. /// This will not return null, but may return an empty array.</returns> internal Rect[] GetBoundingRectangles(ITextPointer start, ITextPointer end, bool clipToView, bool transformToScreen) { ITextView textView = GetUpdatedTextView(); if (textView == null) { return(new Rect[0]); } // If start/end positions are not in the visible range, move them to the first/last visible positions. ReadOnlyCollection <TextSegment> textSegments = textView.TextSegments; if (textSegments.Count > 0) { if (!textView.Contains(start) && start.CompareTo(textSegments[0].Start) < 0) { start = textSegments[0].Start.CreatePointer();; } if (!textView.Contains(end) && end.CompareTo(textSegments[textSegments.Count - 1].End) > 0) { end = textSegments[textSegments.Count - 1].End.CreatePointer(); } } if (!textView.Contains(start) || !textView.Contains(end)) { return(new Rect[0]); } TextRangeAdaptor.MoveToInsertionPosition(start, LogicalDirection.Forward); TextRangeAdaptor.MoveToInsertionPosition(end, LogicalDirection.Backward); Rect visibleRect = Rect.Empty; if (clipToView) { visibleRect = GetVisibleRectangle(textView); // If clipping into view and visible rect is empty, return. if (visibleRect.IsEmpty) { return(new Rect[0]); } } List <Rect> rectangles = new List <Rect>(); ITextPointer position = start.CreatePointer(); while (position.CompareTo(end) < 0) { TextSegment lineRange = textView.GetLineRange(position); if (!lineRange.IsNull) { // Since range is limited to just one line, GetTightBoundingGeometry will return tight bounding // rectangle for given range. It will also work correctly with bidi text. ITextPointer first = (lineRange.Start.CompareTo(start) <= 0) ? start : lineRange.Start; ITextPointer last = (lineRange.End.CompareTo(end) >= 0) ? end : lineRange.End; Rect lineRect = Rect.Empty; Geometry geometry = textView.GetTightBoundingGeometryFromTextPositions(first, last); if (geometry != null) { lineRect = geometry.Bounds; if (clipToView) { lineRect.Intersect(visibleRect); } if (!lineRect.IsEmpty) { if (transformToScreen) { lineRect = new Rect(ClientToScreen(lineRect.TopLeft, textView.RenderScope), ClientToScreen(lineRect.BottomRight, textView.RenderScope)); } rectangles.Add(lineRect); } } } if (position.MoveToLineBoundary(1) == 0) { position = end; } } return(rectangles.ToArray()); }
/// <summary> /// Retrieves the range of a child object. /// </summary> /// <param name="childElementProvider">The child element. A provider should check that the /// passed element is a child of the text container, and should throw an /// InvalidOperationException if it is not.</param> /// <returns>A range that spans the child element.</returns> ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElementProvider) { if (childElementProvider == null) { throw new ArgumentNullException("childElementProvider"); } // Retrieve DependencyObject from AutomationElement DependencyObject childElement; if (_textPeer is TextAutomationPeer) { childElement = ((TextAutomationPeer)_textPeer).ElementFromProvider(childElementProvider); } else { childElement = ((ContentTextAutomationPeer)_textPeer).ElementFromProvider(childElementProvider); } TextRangeAdaptor range = null; if (childElement != null) { ITextPointer rangeStart = null; ITextPointer rangeEnd = null; // Retrieve start and end positions for given element. // If element is TextElement, retrieve its Element Start and End positions. // If element is UIElement hosted by UIContainer (Inlien of Block), // retrieve content Start and End positions of the container. // Otherwise scan ITextContainer to find a range for given element. if (childElement is TextElement) { rangeStart = ((TextElement)childElement).ElementStart; rangeEnd = ((TextElement)childElement).ElementEnd; } else { DependencyObject parent = LogicalTreeHelper.GetParent(childElement); if (parent is InlineUIContainer || parent is BlockUIContainer) { rangeStart = ((TextElement)parent).ContentStart; rangeEnd = ((TextElement)parent).ContentEnd; } else { ITextPointer position = _textContainer.Start.CreatePointer(); while (position.CompareTo(_textContainer.End) < 0) { TextPointerContext context = position.GetPointerContext(LogicalDirection.Forward); if (context == TextPointerContext.ElementStart) { if (childElement == position.GetAdjacentElement(LogicalDirection.Forward)) { rangeStart = position.CreatePointer(LogicalDirection.Forward); position.MoveToElementEdge(ElementEdge.AfterEnd); rangeEnd = position.CreatePointer(LogicalDirection.Backward); break; } } else if (context == TextPointerContext.EmbeddedElement) { if (childElement == position.GetAdjacentElement(LogicalDirection.Forward)) { rangeStart = position.CreatePointer(LogicalDirection.Forward); position.MoveToNextContextPosition(LogicalDirection.Forward); rangeEnd = position.CreatePointer(LogicalDirection.Backward); break; } } position.MoveToNextContextPosition(LogicalDirection.Forward); } } } // Create range if (rangeStart != null && rangeEnd != null) { range = new TextRangeAdaptor(this, rangeStart, rangeEnd, _textPeer); } } if (range == null) { throw new InvalidOperationException(SR.Get(SRID.TextProvider_InvalidChildElement)); } return(range); }
// Token: 0x060065C4 RID: 26052 RVA: 0x001C8254 File Offset: 0x001C6454 internal Rect[] GetBoundingRectangles(ITextPointer start, ITextPointer end, bool clipToView, bool transformToScreen) { ITextView updatedTextView = this.GetUpdatedTextView(); if (updatedTextView == null) { return(new Rect[0]); } ReadOnlyCollection <TextSegment> textSegments = updatedTextView.TextSegments; if (textSegments.Count > 0) { if (!updatedTextView.Contains(start) && start.CompareTo(textSegments[0].Start) < 0) { start = textSegments[0].Start.CreatePointer(); } if (!updatedTextView.Contains(end) && end.CompareTo(textSegments[textSegments.Count - 1].End) > 0) { end = textSegments[textSegments.Count - 1].End.CreatePointer(); } } if (!updatedTextView.Contains(start) || !updatedTextView.Contains(end)) { return(new Rect[0]); } TextRangeAdaptor.MoveToInsertionPosition(start, LogicalDirection.Forward); TextRangeAdaptor.MoveToInsertionPosition(end, LogicalDirection.Backward); Rect rect = Rect.Empty; if (clipToView) { rect = this.GetVisibleRectangle(updatedTextView); if (rect.IsEmpty) { return(new Rect[0]); } } List <Rect> list = new List <Rect>(); ITextPointer textPointer = start.CreatePointer(); while (textPointer.CompareTo(end) < 0) { TextSegment lineRange = updatedTextView.GetLineRange(textPointer); if (!lineRange.IsNull) { ITextPointer startPosition = (lineRange.Start.CompareTo(start) <= 0) ? start : lineRange.Start; ITextPointer endPosition = (lineRange.End.CompareTo(end) >= 0) ? end : lineRange.End; Rect item = Rect.Empty; Geometry tightBoundingGeometryFromTextPositions = updatedTextView.GetTightBoundingGeometryFromTextPositions(startPosition, endPosition); if (tightBoundingGeometryFromTextPositions != null) { item = tightBoundingGeometryFromTextPositions.Bounds; if (clipToView) { item.Intersect(rect); } if (!item.IsEmpty) { if (transformToScreen) { item = new Rect(this.ClientToScreen(item.TopLeft, updatedTextView.RenderScope), this.ClientToScreen(item.BottomRight, updatedTextView.RenderScope)); } list.Add(item); } } } if (textPointer.MoveToLineBoundary(1) == 0) { textPointer = end; } } return(list.ToArray()); }
// Token: 0x060065D1 RID: 26065 RVA: 0x001C8918 File Offset: 0x001C6B18 ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElementProvider) { if (childElementProvider == null) { throw new ArgumentNullException("childElementProvider"); } DependencyObject dependencyObject; if (this._textPeer is TextAutomationPeer) { dependencyObject = ((TextAutomationPeer)this._textPeer).ElementFromProvider(childElementProvider); } else { dependencyObject = ((ContentTextAutomationPeer)this._textPeer).ElementFromProvider(childElementProvider); } TextRangeAdaptor textRangeAdaptor = null; if (dependencyObject != null) { ITextPointer textPointer = null; ITextPointer textPointer2 = null; if (dependencyObject is TextElement) { textPointer = ((TextElement)dependencyObject).ElementStart; textPointer2 = ((TextElement)dependencyObject).ElementEnd; } else { DependencyObject parent = LogicalTreeHelper.GetParent(dependencyObject); if (parent is InlineUIContainer || parent is BlockUIContainer) { textPointer = ((TextElement)parent).ContentStart; textPointer2 = ((TextElement)parent).ContentEnd; } else { ITextPointer textPointer3 = this._textContainer.Start.CreatePointer(); while (textPointer3.CompareTo(this._textContainer.End) < 0) { TextPointerContext pointerContext = textPointer3.GetPointerContext(LogicalDirection.Forward); if (pointerContext == TextPointerContext.ElementStart) { if (dependencyObject == textPointer3.GetAdjacentElement(LogicalDirection.Forward)) { textPointer = textPointer3.CreatePointer(LogicalDirection.Forward); textPointer3.MoveToElementEdge(ElementEdge.AfterEnd); textPointer2 = textPointer3.CreatePointer(LogicalDirection.Backward); break; } } else if (pointerContext == TextPointerContext.EmbeddedElement && dependencyObject == textPointer3.GetAdjacentElement(LogicalDirection.Forward)) { textPointer = textPointer3.CreatePointer(LogicalDirection.Forward); textPointer3.MoveToNextContextPosition(LogicalDirection.Forward); textPointer2 = textPointer3.CreatePointer(LogicalDirection.Backward); break; } textPointer3.MoveToNextContextPosition(LogicalDirection.Forward); } } } if (textPointer != null && textPointer2 != null) { textRangeAdaptor = new TextRangeAdaptor(this, textPointer, textPointer2, this._textPeer); } } if (textRangeAdaptor == null) { throw new InvalidOperationException(SR.Get("TextProvider_InvalidChildElement")); } return(textRangeAdaptor); }