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());
            }
        }
Ejemplo n.º 4
0
        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));
        }
Ejemplo n.º 5
0
        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());
            }
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
        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));
        }
Ejemplo n.º 8
0
        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);
        }