static Rect GetCharacterBounds(this TextView textView, TextViewPosition pos, HwndSource source) { VisualLine vl = textView.GetVisualLine(pos.Line); if (vl == null) { return(EMPTY_RECT); } // this may happen during layout changes in AvalonDock, so we just return an empty rectangle // in those cases. It should be refreshed immediately. if (source.RootVisual == null || !source.RootVisual.IsAncestorOf(textView)) { return(EMPTY_RECT); } TextLine line = vl.GetTextLine(pos.VisualColumn); Rect displayRect; // calculate the display rect for the current character if (pos.VisualColumn < vl.VisualLengthWithEndOfLineMarker) { displayRect = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle; displayRect.Offset(0, vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop)); } else { // if we are in virtual space, we just use one wide-space as character width displayRect = new Rect(vl.GetVisualPosition(pos.VisualColumn, VisualYPosition.TextTop), new Size(textView.WideSpaceWidth, textView.DefaultLineHeight)); } // adjust to current scrolling displayRect.Offset(-textView.ScrollOffset); return(textView .TransformToAncestor(source.RootVisual).TransformBounds(displayRect) // rect on root visual .TransformToDevice(source.RootVisual)); // rect on HWND }
static Rect GetCharacterBounds(this TextView textView, TextViewPosition pos, HwndSource source) { VisualLine vl = textView.GetVisualLine(pos.Line); if (vl == null) { return(EMPTY_RECT); } TextLine line = vl.GetTextLine(pos.VisualColumn); double offset = vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop) - textView.ScrollOffset.Y; Rect r = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle; r.Offset(-textView.ScrollOffset.X, offset); // this may happen during layout changes in AvalonDock, so we just return an empty rectangle // in those cases. It should be refreshed immediately. if (!source.RootVisual.IsAncestorOf(textView)) { return(EMPTY_RECT); } Point pointOnRootVisual = textView.TransformToAncestor(source.RootVisual).Transform(r.Location); Point pointOnHwnd = pointOnRootVisual.TransformToDevice(source.RootVisual); r.Location = pointOnHwnd; return(r); }
internal static TextViewPosition GetNewCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, bool enableVirtualSpace, ref double desiredXPos) { switch (direction) { case CaretMovementType.None: return(caretPosition); case CaretMovementType.DocumentStart: desiredXPos = double.NaN; return(new TextViewPosition(0, 0)); case CaretMovementType.DocumentEnd: desiredXPos = double.NaN; return(new TextViewPosition(textView.Document.GetLocation(textView.Document.TextLength))); } DocumentLine caretLine = textView.Document.GetLineByNumber(caretPosition.Line); VisualLine visualLine = textView.GetOrConstructVisualLine(caretLine); TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn, caretPosition.IsAtEndOfLine); switch (direction) { case CaretMovementType.CharLeft: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace)); case CaretMovementType.Backspace: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.EveryCodepoint, enableVirtualSpace)); case CaretMovementType.CharRight: desiredXPos = double.NaN; return(GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.Normal, enableVirtualSpace)); case CaretMovementType.WordLeft: desiredXPos = double.NaN; return(GetPrevCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace)); case CaretMovementType.WordRight: desiredXPos = double.NaN; return(GetNextCaretPosition(textView, caretPosition, visualLine, CaretPositioningMode.WordStart, enableVirtualSpace)); case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: return(GetUpDownCaretPosition(textView, caretPosition, direction, visualLine, textLine, enableVirtualSpace, ref desiredXPos)); case CaretMovementType.LineStart: desiredXPos = double.NaN; return(GetStartOfLineCaretPosition(caretPosition.VisualColumn, visualLine, textLine, enableVirtualSpace)); case CaretMovementType.LineEnd: desiredXPos = double.NaN; return(GetEndOfLineCaretPosition(visualLine, textLine)); default: throw new NotSupportedException(direction.ToString()); } }
static double GetXPos(TextArea textArea, TextViewPosition pos) { DocumentLine documentLine = textArea.Document.GetLineByNumber(pos.Line); VisualLine visualLine = textArea.TextView.GetOrConstructVisualLine(documentLine); int vc = visualLine.ValidateVisualColumn(pos, true); TextLine textLine = visualLine.GetTextLine(vc); return(visualLine.GetTextLineVisualXPosition(textLine, vc)); }
static void MoveCaret(TextArea textArea, CaretMovementType direction) { DocumentLine caretLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); VisualLine visualLine = textArea.TextView.GetOrConstructVisualLine(caretLine); TextViewPosition caretPosition = textArea.Caret.Position; TextLine textLine = visualLine.GetTextLine(caretPosition.VisualColumn); switch (direction) { case CaretMovementType.CharLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.CharRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.Normal); break; case CaretMovementType.WordLeft: MoveCaretLeft(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.WordRight: MoveCaretRight(textArea, caretPosition, visualLine, CaretPositioningMode.WordStart); break; case CaretMovementType.LineUp: case CaretMovementType.LineDown: case CaretMovementType.PageUp: case CaretMovementType.PageDown: MoveCaretUpDown(textArea, direction, visualLine, textLine, caretPosition.VisualColumn); break; case CaretMovementType.DocumentStart: SetCaretPosition(textArea, 0, 0); break; case CaretMovementType.DocumentEnd: SetCaretPosition(textArea, -1, textArea.Document.TextLength); break; case CaretMovementType.LineStart: MoveCaretToStartOfLine(textArea, visualLine); break; case CaretMovementType.LineEnd: MoveCaretToEndOfLine(textArea, visualLine); break; default: throw new NotSupportedException(direction.ToString()); } }
int GetTextLineIndexFromOffset(List <TextLine> textLines, int offset) { int lineNumber = TextView.Document.GetLineByOffset(offset).LineNumber; VisualLine vl = TextView.GetVisualLine(lineNumber); if (vl != null) { int relOffset = offset - vl.FirstDocumentLine.Offset; TextLine line = vl.GetTextLine(vl.GetVisualColumn(relOffset)); return(textLines.IndexOf(line)); } return(-1); }
Rect CalcCaretRectangle(VisualLine visualLine) { if (!visualColumnValid) { RevalidateVisualColumn(visualLine); } TextLine textLine = visualLine.GetTextLine(position.VisualColumn); double xPos = visualLine.GetTextLineVisualXPosition(textLine, position.VisualColumn); double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop); double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom); return(new Rect(xPos, lineTop, SystemParameters.CaretWidth, lineBottom - lineTop)); }
Rect CalcCaretOverstrikeRectangle(VisualLine visualLine) { if (!visualColumnValid) { RevalidateVisualColumn(visualLine); } int currentPos = position.VisualColumn; // The text being overwritten in overstrike mode is everything up to the next normal caret stop int nextPos = visualLine.GetNextCaretPosition(currentPos, LogicalDirection.Forward, CaretPositioningMode.Normal, true); TextLine textLine = visualLine.GetTextLine(currentPos); Rect r; if (currentPos < visualLine.VisualLength) { // If the caret is within the text, use GetTextBounds() for the text being overwritten. // This is necessary to ensure the rectangle is calculated correctly in bidirectional text. var textBounds = textLine.GetTextBounds(currentPos, nextPos - currentPos)[0]; r = textBounds.Rectangle; r.Y += visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineTop); } else { // If the caret is at the end of the line (or in virtual space), // use the visual X position of currentPos and nextPos (one or more of which will be in virtual space) double xPos = visualLine.GetTextLineVisualXPosition(textLine, currentPos); double xPos2 = visualLine.GetTextLineVisualXPosition(textLine, nextPos); double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop); double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom); r = new Rect(xPos, lineTop, xPos2 - xPos, lineBottom - lineTop); } // If the caret is too small (e.g. in front of zero-width character), ensure it's still visible if (r.Width < SystemParameters.CaretWidth) { r.Width = SystemParameters.CaretWidth; } return(r); }