// Token: 0x06003889 RID: 14473 RVA: 0x000FDB54 File Offset: 0x000FBD54 private static UIElement GetUIElementWhenMouseOver(TextEditor This, Point mouseMovePoint) { ITextPointer textPositionFromPoint = This.TextView.GetTextPositionFromPoint(mouseMovePoint, false); if (textPositionFromPoint == null) { return(null); } if (textPositionFromPoint.GetPointerContext(textPositionFromPoint.LogicalDirection) != TextPointerContext.EmbeddedElement) { return(null); } ITextPointer textPointer = textPositionFromPoint.GetNextContextPosition(textPositionFromPoint.LogicalDirection); LogicalDirection gravity = (textPositionFromPoint.LogicalDirection == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward; textPointer = textPointer.CreatePointer(0, gravity); Rect rectangleFromTextPosition = This.TextView.GetRectangleFromTextPosition(textPositionFromPoint); Rect rectangleFromTextPosition2 = This.TextView.GetRectangleFromTextPosition(textPointer); Rect rect = rectangleFromTextPosition; rect.Union(rectangleFromTextPosition2); if (!rect.Contains(mouseMovePoint)) { return(null); } return(textPositionFromPoint.GetAdjacentElement(textPositionFromPoint.LogicalDirection) as UIElement); }
// Token: 0x0600384C RID: 14412 RVA: 0x000FB73C File Offset: 0x000F993C private static ITextPointer GetContentPosition(ITextPointer position) { while (position.GetAdjacentElement(LogicalDirection.Forward) is Inline) { position = position.GetNextContextPosition(LogicalDirection.Forward); } return(position); }
// Return a UIElement when mouseMovePoint is within the ui element's bounding Rect. Null otherwise. private static UIElement GetUIElementWhenMouseOver(TextEditor This, Point mouseMovePoint) { ITextPointer mouseMovePosition = This.TextView.GetTextPositionFromPoint(mouseMovePoint, /*snapToText:*/ false); if (mouseMovePosition == null) { return(null); } if (!(mouseMovePosition.GetPointerContext(mouseMovePosition.LogicalDirection) == TextPointerContext.EmbeddedElement)) { return(null); } // Find out if mouseMovePoint is within the bounding Rect of UIElement, we need to do this check explicitly // because even when snapToText is false, textview returns a first/last position on a line when point is in // an area before/after line start/end. This is by-design behavior for textview. // Need to get Rect from TextView, since Rect returned by TextPointer.GetCharacterRect() // is transformed to UiScope coordinates and we want RenderScope coordinates here. ITextPointer otherEdgePosition = mouseMovePosition.GetNextContextPosition(mouseMovePosition.LogicalDirection); LogicalDirection otherEdgeDirection = (mouseMovePosition.LogicalDirection == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward; // Normalize with correct gravity otherEdgePosition = otherEdgePosition.CreatePointer(0, otherEdgeDirection); Rect uiElementFirstEdgeRect = This.TextView.GetRectangleFromTextPosition(mouseMovePosition); Rect uiElementSecondEdgeRect = This.TextView.GetRectangleFromTextPosition(otherEdgePosition); Rect boundingRect = uiElementFirstEdgeRect; boundingRect.Union(uiElementSecondEdgeRect); if (!boundingRect.Contains(mouseMovePoint)) { return(null); } return(mouseMovePosition.GetAdjacentElement(mouseMovePosition.LogicalDirection) as UIElement); }
// ------------------------------------------------------------- // // Private Methods // // ------------------------------------------------------------- #region Private Methods // ............................................................. // // Serialization // // ............................................................. /// <summary> /// This function serializes text segment formed by rangeStart and rangeEnd to valid xml using xmlWriter. /// </summary> /// <SecurityNote> /// To mask the security exception from XamlWriter.Save in partial trust case, /// this function checks if the current call stack has the all clipboard permission. /// </SecurityNote> private static void WriteXamlTextSegment(XmlWriter xmlWriter, ITextPointer rangeStart, ITextPointer rangeEnd, XamlTypeMapper xamlTypeMapper, ref int elementLevel, WpfPayload wpfPayload, bool ignoreWriteHyperlinkEnd, List<int> ignoreList, bool preserveTextElements) { // Special case for pure text selection - we need a Run wrapper for it. if (elementLevel == EmptyDocumentDepth && typeof(Run).IsAssignableFrom(rangeStart.ParentType)) { elementLevel++; xmlWriter.WriteStartElement(typeof(Run).Name); } // Create text navigator for reading the range's content ITextPointer textReader = rangeStart.CreatePointer(); // Exclude last opening tag from serialization - we don't need to create extra element // is cases when we have whole paragraphs/cells selected. // NOTE: We do this slightly differently than in TextRangeEdit.AdjustRangeEnd, where we use normalization for adjusted position. // In this case normalized position does not work, because we need to keep information about crossed paragraph boundary. while (rangeEnd.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) { rangeEnd = rangeEnd.GetNextContextPosition(LogicalDirection.Backward); } // Write the range internal contents while (textReader.CompareTo(rangeEnd) < 0) { TextPointerContext runType = textReader.GetPointerContext(LogicalDirection.Forward); switch (runType) { case TextPointerContext.ElementStart: TextElement nextElement = (TextElement)textReader.GetAdjacentElement(LogicalDirection.Forward); if (nextElement is Hyperlink) { // Don't write Hyperlink start element if Hyperlink is invalid // in case of having a UiElement except Image or stated the range end // position before the end position of the Hyperlink. if (IsHyperlinkInvalid(textReader, rangeEnd)) { ignoreWriteHyperlinkEnd = true; textReader.MoveToNextContextPosition(LogicalDirection.Forward); continue; } } else if (nextElement != null) { // TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(nextElement.GetType(), typeof(TextElementEditingBehaviorAttribute)); if (att != null && !att.IsTypographicOnly) { if (IsPartialNonTypographic(textReader, rangeEnd)) { // Add pointer to ignore list ITextPointer ptr = textReader.CreatePointer(); ptr.MoveToElementEdge(ElementEdge.BeforeEnd); ignoreList.Add(ptr.Offset); textReader.MoveToNextContextPosition(LogicalDirection.Forward); continue; } } } elementLevel++; textReader.MoveToNextContextPosition(LogicalDirection.Forward); WriteStartXamlElement(/*range:*/null, textReader, xmlWriter, xamlTypeMapper, /*reduceElement:*/wpfPayload == null, preserveTextElements); break; case TextPointerContext.ElementEnd: // Don't write Hyperlink end element if Hyperlink include the invalid // in case of having a UiElement except Image or stated the range end // before the end position of the Hyperlink or Hyperlink opening tag is // skipped from WriteOpeningTags by selecting of the partial of Hyperlink. if (ignoreWriteHyperlinkEnd && (textReader.GetAdjacentElement(LogicalDirection.Forward) is Hyperlink)) { // Reset the flag to keep walk up the next Hyperlink tag ignoreWriteHyperlinkEnd = false; textReader.MoveToNextContextPosition(LogicalDirection.Forward); continue; } // Check the ignore list ITextPointer endPointer = textReader.CreatePointer(); endPointer.MoveToElementEdge(ElementEdge.BeforeEnd); // if (ignoreList.Contains(endPointer.Offset)) { ignoreList.Remove(endPointer.Offset); textReader.MoveToNextContextPosition(LogicalDirection.Forward); continue; } elementLevel--; if (TextSchema.IsBreak(textReader.ParentType)) { // For LineBreak, etc. use empty element syntax xmlWriter.WriteEndElement(); } else { // // For all other textelements use explicit closing tag. xmlWriter.WriteFullEndElement(); } textReader.MoveToNextContextPosition(LogicalDirection.Forward); break; case TextPointerContext.Text: int textLength = textReader.GetTextRunLength(LogicalDirection.Forward); char[] text = new Char[textLength]; textLength = TextPointerBase.GetTextWithLimit(textReader, LogicalDirection.Forward, text, 0, textLength, rangeEnd); // XmlWriter will throw an ArgumentException if text contains // any invalid surrogates, so strip them out now. textLength = StripInvalidSurrogateChars(text, textLength); xmlWriter.WriteChars(text, 0, textLength); textReader.MoveToNextContextPosition(LogicalDirection.Forward); break; case TextPointerContext.EmbeddedElement: object embeddedObject = textReader.GetAdjacentElement(LogicalDirection.Forward); textReader.MoveToNextContextPosition(LogicalDirection.Forward); WriteEmbeddedObject(embeddedObject, xmlWriter, wpfPayload); break; default: Invariant.Assert(false, "unexpected value of runType"); textReader.MoveToNextContextPosition(LogicalDirection.Forward); break; } } }
//...................................................... // // Selection Building With Mouse // //...................................................... // Moves the selection to the mouse cursor position. // If the cursor is facing a UIElement, select the UIElement. // Sets new selection anchor to a given cursorPosition. private void MoveSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint) { ITextSelection thisSelection = (ITextSelection)this; if (this.TextView == null) { return; } Invariant.Assert(this.TextView.IsValid); // We just checked RenderScope. We'll use TextView below ITextPointer movingPosition = null; if (cursorPosition.GetPointerContext(cursorPosition.LogicalDirection) == TextPointerContext.EmbeddedElement) { Rect objectEdgeRect = this.TextView.GetRectangleFromTextPosition(cursorPosition); // Check for embedded object. // If the click happend inside of it we need to select it as a whole, when content is not read-only. if (!_textEditor.IsReadOnly && ShouldSelectEmbeddedObject(cursorPosition, cursorMousePoint, objectEdgeRect)) { movingPosition = cursorPosition.GetNextContextPosition(cursorPosition.LogicalDirection); } } // Move selection to this position if (movingPosition == null) { thisSelection.SetCaretToPosition(cursorPosition, cursorPosition.LogicalDirection, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/false); } else { thisSelection.Select(cursorPosition, movingPosition); } }
// Returns true if pointer is at the start of a paragraph. internal static bool IsAtParagraphOrBlockUIContainerStart(ITextPointer pointer) { // Is pointer at a potential paragraph position? if (IsAtPotentialParagraphPosition(pointer)) { return true; } // Can you find a <Paragraph> start tag looking backwards? // Loop to skip multiple formatting opening tags, never crossing parent element boundary. while (pointer.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) { if (TextSchema.IsParagraphOrBlockUIContainer(pointer.ParentType)) { return true; } pointer = pointer.GetNextContextPosition(LogicalDirection.Backward); } return false; }
private static ITextPointer RestrictWithinBlock(ITextPointer position, ITextPointer limit, LogicalDirection direction) { Invariant.Assert(!(direction == LogicalDirection.Backward) || position.CompareTo(limit) >= 0, "for backward direction position must be >= than limit"); Invariant.Assert(!(direction == LogicalDirection.Forward) || position.CompareTo(limit) <= 0, "for forward direcion position must be <= than linit"); while (direction == LogicalDirection.Backward ? position.CompareTo(limit) > 0 : position.CompareTo(limit) < 0) { TextPointerContext context = position.GetPointerContext(direction); if (context == TextPointerContext.ElementStart || context == TextPointerContext.ElementEnd) { Type elementType = position.GetElementType(direction); if (!typeof(Inline).IsAssignableFrom(elementType)) { limit = position; break; } } else if (context == TextPointerContext.EmbeddedElement) { limit = position; break; } position = position.GetNextContextPosition(direction); } // Return normalized position - in the direction towards a center position. return limit.GetInsertionPosition(direction == LogicalDirection.Backward ? LogicalDirection.Forward : LogicalDirection.Backward); }
// Returns true if the position is adjacent to a LineBreak or Paragraph element, // ignoring any intermediate formatting elements. // // If lineBreakType is null, any line break element is considered valid. private static bool IsNextToRichBreak(ITextPointer thisPosition, LogicalDirection direction, Type lineBreakType) { Invariant.Assert(lineBreakType == null || lineBreakType == typeof(LineBreak) || lineBreakType == typeof(Paragraph)); bool result = false; while (true) { Type neighbor = thisPosition.GetElementType(direction); if (lineBreakType == null) { if (typeof(LineBreak).IsAssignableFrom(neighbor) || typeof(Paragraph).IsAssignableFrom(neighbor)) { result = true; break; } } else if (lineBreakType.IsAssignableFrom(neighbor)) { result = true; break; } if (!TextSchema.IsFormattingType(neighbor)) break; thisPosition = thisPosition.GetNextContextPosition(direction); } return result; }
// Returns a position ajacent to the supplied position, skipping any // intermediate Inlines. // This is useful for sliding inside the context of adjacent Hyperlinks, // Spans, etc. private static ITextPointer GetContentPosition(ITextPointer position) { while (position.GetAdjacentElement(LogicalDirection.Forward) is Inline) { position = position.GetNextContextPosition(LogicalDirection.Forward); } return position; }
// Tests if the position is at the beginning of some list item - // to allow Backspace to delete the bullet. private static bool IsAtListItemStart(ITextPointer position) { // Check for empty ListItem case if (typeof(ListItem).IsAssignableFrom(position.ParentType) && position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart && position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd) { return true; } while (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) { Type parentType = position.ParentType; if (TextSchema.IsBlock(parentType)) { if (TextSchema.IsParagraphOrBlockUIContainer(parentType)) { position = position.GetNextContextPosition(LogicalDirection.Backward); if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart && typeof(ListItem).IsAssignableFrom(position.ParentType)) { return true; } } return false; } position = position.GetNextContextPosition(LogicalDirection.Backward); } return false; }