static IEnumerable<Rect> GetRectsForSegmentImpl(TextView textView, ISegment segment, bool extendToFullWidthAtLineEnd)
		{
			int segmentStart = segment.Offset;
			int segmentEnd = segment.Offset + segment.Length;
			
			segmentStart = segmentStart.CoerceValue(0, textView.Document.TextLength);
			segmentEnd = segmentEnd.CoerceValue(0, textView.Document.TextLength);
			
			TextViewPosition start;
			TextViewPosition end;
			
			if (segment is SelectionSegment) {
				SelectionSegment sel = (SelectionSegment)segment;
				start = new TextViewPosition(textView.Document.GetLocation(sel.StartOffset), sel.StartVisualColumn);
				end = new TextViewPosition(textView.Document.GetLocation(sel.EndOffset), sel.EndVisualColumn);
			} else {
				start = new TextViewPosition(textView.Document.GetLocation(segmentStart));
				end = new TextViewPosition(textView.Document.GetLocation(segmentEnd));
			}
			
			foreach (VisualLine vl in textView.VisualLines) {
				int vlStartOffset = vl.FirstDocumentLine.Offset;
				if (vlStartOffset > segmentEnd)
					break;
				int vlEndOffset = vl.LastDocumentLine.Offset + vl.LastDocumentLine.Length;
				if (vlEndOffset < segmentStart)
					continue;
				
				int segmentStartVC;
				if (segmentStart < vlStartOffset)
					segmentStartVC = 0;
				else
					segmentStartVC = vl.ValidateVisualColumn(start, extendToFullWidthAtLineEnd);
				
				int segmentEndVC;
				if (segmentEnd > vlEndOffset)
					segmentEndVC = extendToFullWidthAtLineEnd ? int.MaxValue : vl.VisualLengthWithEndOfLineMarker;
				else
					segmentEndVC = vl.ValidateVisualColumn(end, extendToFullWidthAtLineEnd);
				
				foreach (var rect in ProcessTextLines(textView, vl, segmentStartVC, segmentEndVC))
					yield return rect;
			}
		}
Exemplo n.º 2
0
        public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs)
        {
            if (replaceOffset == -1)
            {
                var token = CodeCompletion.GetToken(textArea);
                this.replaceOffset = token.Length;
            }

            if (String.IsNullOrEmpty(this.actualText))
            {
                ;
            }
            this.actualText = this.Text;
            var replaceSegment = new SelectionSegment(completionSegment.Offset - this.replaceOffset, completionSegment.EndOffset);

            textArea.Document.Replace(replaceSegment, GetActualTextAndSetOffset(this.actualText));
            // 输入补全条目后进行光标位置偏移
            textArea.Caret.Offset = textArea.Caret.Offset - this.completeOffset;
        }
        static IEnumerable <Rect> GetRectsForSegmentImpl(TextView textView, ISegment segment, bool extendToFullWidthAtLineEnd)
        {
            Vector scrollOffset = textView.ScrollOffset;
            int    segmentStart = segment.Offset;
            int    segmentEnd   = segment.Offset + segment.Length;

            segmentStart = segmentStart.CoerceValue(0, textView.Document.TextLength);
            segmentEnd   = segmentEnd.CoerceValue(0, textView.Document.TextLength);

            TextViewPosition start;
            TextViewPosition end;

            if (segment is SelectionSegment)
            {
                SelectionSegment sel = (SelectionSegment)segment;
                start = new TextViewPosition(textView.Document.GetLocation(sel.StartOffset), sel.StartVisualColumn);
                end   = new TextViewPosition(textView.Document.GetLocation(sel.EndOffset), sel.EndVisualColumn);
            }
            else
            {
                start = new TextViewPosition(textView.Document.GetLocation(segmentStart), -1);
                end   = new TextViewPosition(textView.Document.GetLocation(segmentEnd), -1);
            }

            foreach (VisualLine vl in textView.VisualLines)
            {
                int vlStartOffset = vl.FirstDocumentLine.Offset;
                if (vlStartOffset > segmentEnd)
                {
                    break;
                }
                int vlEndOffset = vl.LastDocumentLine.Offset + vl.LastDocumentLine.Length;
                if (vlEndOffset < segmentStart)
                {
                    continue;
                }

                int segmentStartVC;
                if (segmentStart < vlStartOffset)
                {
                    segmentStartVC = 0;
                }
                else
                {
                    segmentStartVC = vl.ValidateVisualColumn(start, extendToFullWidthAtLineEnd);
                }

                int segmentEndVC;
                if (segmentEnd > vlEndOffset)
                {
                    segmentEndVC = extendToFullWidthAtLineEnd ? int.MaxValue : vl.VisualLengthWithEndOfLineMarker;
                }
                else
                {
                    segmentEndVC = vl.ValidateVisualColumn(end, extendToFullWidthAtLineEnd);
                }

                TextLine lastTextLine = vl.TextLines.Last();

                for (int i = 0; i < vl.TextLines.Count; i++)
                {
                    TextLine line           = vl.TextLines[i];
                    double   y              = vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop);
                    int      visualStartCol = vl.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 = vl.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 < vl.TextLines.Count - 1 && segmentEndVC > segmentEndVCInLine && line.TrailingWhitespaceLength == 0)
                        {
                            continue;
                        }
                        if (segmentStartVCInLine == visualStartCol && i > 0 && segmentStartVC < segmentStartVCInLine && vl.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 >= vl.VisualLengthWithEndOfLineMarker)
                        {
                            double left            = (segmentStartVC > vl.VisualLengthWithEndOfLineMarker ? vl.GetTextLineVisualXPosition(lastTextLine, segmentStartVC) : line.Width) - scrollOffset.X;
                            double right           = ((segmentEndVC == int.MaxValue || line != lastTextLine) ? Math.Max(((IScrollInfo)textView).ExtentWidth, ((IScrollInfo)textView).ViewportWidth) : vl.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);
                        }
                    }
                }
            }
        }