static IEnumerable<Rect> ProcessTextLines(TextView textView, VisualLine visualLine, int segmentStartVC, int segmentEndVC)
        {
            TextLine lastTextLine = visualLine.TextLines.Last();
            Vector scrollOffset = textView.ScrollOffset;

            for (int i = 0; i < visualLine.TextLines.Count; i++) {
                TextLine line = visualLine.TextLines[i];
                double y = visualLine.GetTextLineVisualYPosition(line, VisualYPosition.LineTop);
                int visualStartCol = visualLine.GetTextLineVisualStartColumn(line);
                int visualEndCol = visualStartCol + line.Length;
                if (line != lastTextLine)
                    visualEndCol -= line.TrailingWhitespaceLength;

                if (segmentEndVC < visualStartCol)
                    break;
                if (lastTextLine != line && segmentStartVC > visualEndCol)
                    continue;
                int segmentStartVCInLine = Math.Max(segmentStartVC, visualStartCol);
                int segmentEndVCInLine = Math.Min(segmentEndVC, visualEndCol);
                y -= scrollOffset.Y;
                if (segmentStartVCInLine == segmentEndVCInLine) {
                    // GetTextBounds crashes for length=0, so we'll handle this case with GetDistanceFromCharacterHit
                    // We need to return a rectangle to ensure empty lines are still visible
                    double pos = visualLine.GetTextLineVisualXPosition(line, segmentStartVCInLine);
                    pos -= scrollOffset.X;
                    // The following special cases are necessary to get rid of empty rectangles at the end of a TextLine if "Show Spaces" is active.
                    // If not excluded once, the same rectangle is calculated (and added) twice (since the offset could be mapped to two visual positions; end/start of line), if there is no trailing whitespace.
                    // Skip this TextLine segment, if it is at the end of this line and this line is not the last line of the VisualLine and the selection continues and there is no trailing whitespace.
                    if (segmentEndVCInLine == visualEndCol && i < visualLine.TextLines.Count - 1 && segmentEndVC > segmentEndVCInLine && line.TrailingWhitespaceLength == 0)
                        continue;
                    if (segmentStartVCInLine == visualStartCol && i > 0 && segmentStartVC < segmentStartVCInLine && visualLine.TextLines[i - 1].TrailingWhitespaceLength == 0)
                        continue;
                    yield return new Rect(pos, y, 1, line.Height);
                } else {
                    Rect lastRect = Rect.Empty;
                    if (segmentStartVCInLine <= visualEndCol) {
                        foreach (TextBounds b in line.GetTextBounds(segmentStartVCInLine, segmentEndVCInLine - segmentStartVCInLine)) {
                            double left = b.Rectangle.Left - scrollOffset.X;
                            double right = b.Rectangle.Right - scrollOffset.X;
                            if (!lastRect.IsEmpty)
                                yield return lastRect;
                            // left>right is possible in RTL languages
                            lastRect = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
                        }
                    }
                    if (segmentEndVC >= visualLine.VisualLengthWithEndOfLineMarker) {
                        double left = (segmentStartVC > visualLine.VisualLengthWithEndOfLineMarker ? visualLine.GetTextLineVisualXPosition(lastTextLine, segmentStartVC) : line.Width) - scrollOffset.X;
                        double right = ((segmentEndVC == int.MaxValue || line != lastTextLine) ? Math.Max(((IScrollInfo)textView).ExtentWidth, ((IScrollInfo)textView).ViewportWidth) : visualLine.GetTextLineVisualXPosition(lastTextLine, segmentEndVC)) - scrollOffset.X;
                        Rect extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
                        if (!lastRect.IsEmpty) {
                            if (extendSelection.IntersectsWith(lastRect)) {
                                lastRect.Union(extendSelection);
                                yield return lastRect;
                            } else {
                                yield return lastRect;
                                yield return extendSelection;
                            }
                        } else
                            yield return extendSelection;
                    } else
                        yield return lastRect;
                }
            }
        }
Ejemplo n.º 2
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);
        }
 static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn)
 {
     // moving up/down happens using the desired visual X position
     double xPos = textArea.Caret.DesiredXPos;
     if (double.IsNaN(xPos))
         xPos = visualLine.GetTextLineVisualXPosition(textLine, caretVisualColumn);
     // now find the TextLine+VisualLine where the caret will end up in
     VisualLine targetVisualLine = visualLine;
     TextLine targetLine;
     int textLineIndex = visualLine.TextLines.IndexOf(textLine);
     switch (direction) {
         case CaretMovementType.LineUp:
             {
                 // Move up: move to the previous TextLine in the same visual line
                 // or move to the last TextLine of the previous visual line
                 int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1;
                 if (textLineIndex > 0) {
                     targetLine = visualLine.TextLines[textLineIndex - 1];
                 } else if (prevLineNumber >= 1) {
                     DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber);
                     targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine);
                     targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1];
                 } else {
                     targetLine = null;
                 }
                 break;
             }
         case CaretMovementType.LineDown:
             {
                 // Move down: move to the next TextLine in the same visual line
                 // or move to the first TextLine of the next visual line
                 int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1;
                 if (textLineIndex < visualLine.TextLines.Count - 1) {
                     targetLine = visualLine.TextLines[textLineIndex + 1];
                 } else if (nextLineNumber <= textArea.Document.LineCount) {
                     DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber);
                     targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine);
                     targetLine = targetVisualLine.TextLines[0];
                 } else {
                     targetLine = null;
                 }
                 break;
             }
         case CaretMovementType.PageUp:
         case CaretMovementType.PageDown:
             {
                 // Page up/down: find the target line using its visual position
                 double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle);
                 if (direction == CaretMovementType.PageUp)
                     yPos -= textArea.TextView.RenderSize.Height;
                 else
                     yPos += textArea.TextView.RenderSize.Height;
                 DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos);
                 targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine);
                 targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos);
                 break;
             }
         default:
             throw new NotSupportedException(direction.ToString());
     }
     if (targetLine != null) {
         double yPos = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle);
         int newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), textArea.Selection.EnableVirtualSpace);
         SetCaretPosition(textArea, targetVisualLine, targetLine, newVisualColumn, false);
         textArea.Caret.DesiredXPos = xPos;
     }
 }