Example #1
0
 /// <summary>
 /// Creates a visual line text element with the specified length.
 /// It uses the <see cref="ITextRunConstructionContext.VisualLine"/> and its
 /// <see cref="VisualLineElement.RelativeTextOffset"/> to find the actual text string.
 /// </summary>
 public VisualLineLinkText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length)
 {
     RequireControlModifierForClick = true;
 }
Example #2
0
        private static IEnumerable <Rect> ProcessTextLines(TextView textView, VisualLine visualLine, int segmentStartVc, int segmentEndVc)
        {
            var lastTextLine = visualLine.TextLines.Last();
            var scrollOffset = textView.ScrollOffset;

            for (var i = 0; i < visualLine.TextLines.Count; i++)
            {
                var line           = visualLine.TextLines[i];
                var y              = visualLine.GetTextLineVisualYPosition(line, VisualYPosition.LineTop);
                var visualStartCol = visualLine.GetTextLineVisualStartColumn(line);
                var visualEndCol   = visualStartCol + line.Length;
                if (line == lastTextLine)
                {
                    visualEndCol -= 1;                              // 1 position for the TextEndOfParagraph
                }
                else                                                // TODO: ?
                {
                    visualEndCol -= line.TrailingWhitespaceLength;  //else
                }
                //	visualEndCol -= line.TrailingWhitespaceLength;

                if (segmentEndVc < visualStartCol)
                {
                    break;
                }
                if (lastTextLine != line && segmentStartVc > visualEndCol)
                {
                    continue;
                }
                var segmentStartVcInLine = Math.Max(segmentStartVc, visualStartCol);
                var segmentEndVcInLine   = Math.Min(segmentEndVc, visualEndCol);
                y -= scrollOffset.Y;
                var lastRect = Rect.Empty;
                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
                    var 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;
                    }
                    lastRect = new Rect(pos, y, textView.EmptyLineSelectionWidth, line.Height);
                }
                else
                {
                    if (segmentStartVcInLine <= visualEndCol)
                    {
                        var b     = line.GetTextBounds(segmentStartVcInLine, segmentEndVcInLine - segmentStartVcInLine);
                        var left  = b.X - scrollOffset.X;
                        var right = b.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 the segment ends in virtual space, extend the last rectangle with the rectangle the portion of the selection
                // after the line end.
                // Also, when word-wrap is enabled and the segment continues into the next line, extend lastRect up to the end of the line.
                if (segmentEndVc > visualEndCol)
                {
                    double left, right;
                    if (segmentStartVc > visualLine.VisualLengthWithEndOfLineMarker)
                    {
                        // segmentStartVC is in virtual space
                        left = visualLine.GetTextLineVisualXPosition(lastTextLine, segmentStartVc);
                    }
                    else
                    {
                        // Otherwise, we already processed the rects from segmentStartVC up to visualEndCol,
                        // so we only need to do the remainder starting at visualEndCol.
                        // For word-wrapped lines, visualEndCol doesn't include the whitespace hidden by the wrap,
                        // so we'll need to include it here.
                        // For the last line, visualEndCol already includes the whitespace.
                        left = line == lastTextLine ? line.WidthIncludingTrailingWhitespace : line.Width;
                    }
                    // TODO: !!!!!!!!!!!!!!!!!! SCROLL !!!!!!!!!!!!!!!!!!
                    if (line != lastTextLine || segmentEndVc == int.MaxValue)
                    {
                        //	// If word-wrap is enabled and the segment continues into the next line,
                        //	// or if the extendToFullWidthAtLineEnd option is used (segmentEndVC == int.MaxValue),
                        //	// we select the full width of the viewport.
                        right = Math.Max(((ILogicalScrollable)textView).Extent.Width, ((ILogicalScrollable)textView).Viewport.Width);
                    }
                    else
                    {
                        right = visualLine.GetTextLineVisualXPosition(lastTextLine, segmentEndVc);
                    }
                    var extendSelection = new Rect(Math.Min(left, right), y, Math.Abs(right - left), line.Height);
                    if (!lastRect.IsEmpty)
                    {
                        if (extendSelection.Intersects(lastRect))
                        {
                            lastRect.Union(extendSelection);
                            yield return(lastRect);
                        }
                        else
                        {
                            // If the end of the line is in an RTL segment, keep lastRect and extendSelection separate.
                            yield return(lastRect);

                            yield return(extendSelection);
                        }
                    }
                    else
                    {
                        yield return(extendSelection);
                    }
                }
                else
                {
                    yield return(lastRect);
                }
            }
        }
Example #3
0
 public VisualLineDrawingVisual(VisualLine visualLine)
 {
     VisualLine = visualLine;
     LineHeight = VisualLine.TextLines.Sum(textLine => textLine.Height);
 }
Example #4
0
 /// <summary>
 /// Calculates the rectangles for the visual column segment.
 /// This returns one rectangle for each line inside the segment.
 /// </summary>
 public static IEnumerable <Rect> GetRectsFromVisualSegment(TextView textView, VisualLine line, int startVc, int endVc)
 {
     if (textView == null)
     {
         throw new ArgumentNullException(nameof(textView));
     }
     if (line == null)
     {
         throw new ArgumentNullException(nameof(line));
     }
     return(ProcessTextLines(textView, line, startVc, endVc));
 }
Example #5
0
 public VisualLineTextSource(VisualLine visualLine)
 {
     VisualLine = visualLine;
 }