public static Geometry?CreateGeometry(IWpfTextView textView, VirtualSnapshotSpan span, bool isMultiLine, bool clipToViewport = false) { var padding = isMultiLine ? LineMarkerPadding : TextMarkerPadding; var pos = span.Start; PathGeometry?geo = null; bool createOutlinedPath = false; while (pos <= span.End) { var line = textView.GetTextViewLineContainingBufferPosition(pos.Position); bool useVspaces = line.IsLastDocumentLine(); var lineExtent = new VirtualSnapshotSpan(new VirtualSnapshotPoint(line.Start), new VirtualSnapshotPoint(line.EndIncludingLineBreak, useVspaces ? span.End.VirtualSpaces : 0)); var extentTmp = lineExtent.Intersection(new VirtualSnapshotSpan(pos, span.End)); Debug2.Assert(!(extentTmp is null)); if (line.VisibilityState != VisibilityState.Unattached && !(extentTmp is null) && extentTmp.Value.Length != 0) { var extent = extentTmp.Value; Collection <TextBounds> textBounds; if (extent.Start.IsInVirtualSpace) { var leading = line.TextRight + extent.Start.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; double width = line.EndOfLineWidth; int vspaces = span.End.VirtualSpaces - span.Start.VirtualSpaces; if (vspaces > 0) { width = vspaces * textView.FormattedLineSource.ColumnWidth; } textBounds = new Collection <TextBounds>(); textBounds.Add(new TextBounds(leading, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else if (extent.End.IsInVirtualSpace) { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); double width = extent.End.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; textBounds.Add(new TextBounds(line.TextRight, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); } AddGeometries(textView, textBounds, isMultiLine, clipToViewport, padding, SystemParameters.CaretWidth, ref geo, ref createOutlinedPath); } if (line.IsLastDocumentLine()) { break; } pos = new VirtualSnapshotPoint(line.GetPointAfterLineBreak()); } if (createOutlinedPath) { geo = geo !.GetOutlinedPathGeometry(); } if (!(geo is null) && geo.CanFreeze) { geo.Freeze(); } return(geo); }
public static Geometry CreateBoxGeometry(IWpfTextView textView, IList <VirtualSnapshotSpan> spans, bool isMultiLine, bool clipToViewport = false) { var padding = isMultiLine ? LineMarkerPadding : TextMarkerPadding; PathGeometry geo = null; bool createOutlinedPath = false; foreach (var span in spans) { var line = textView.GetTextViewLineContainingBufferPosition(span.SnapshotSpan.Start); Debug.Assert(span.SnapshotSpan.End <= line.EndIncludingLineBreak); var lineExtent = new VirtualSnapshotSpan(new VirtualSnapshotPoint(line.Start), new VirtualSnapshotPoint(line.EndIncludingLineBreak, span.End.VirtualSpaces)); var extentTmp = lineExtent.Intersection(span); Debug.Assert(extentTmp != null); if (line.VisibilityState != VisibilityState.Unattached && extentTmp != null) { var extent = extentTmp.Value; Collection <TextBounds> textBounds; if (extent.Start.IsInVirtualSpace) { var leading = line.TextRight + extent.Start.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; double width = line.EndOfLineWidth; int vspaces = span.End.VirtualSpaces - span.Start.VirtualSpaces; if (vspaces > 0) { width = vspaces * textView.FormattedLineSource.ColumnWidth; } textBounds = new Collection <TextBounds>(); textBounds.Add(new TextBounds(leading, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else if (extent.End.IsInVirtualSpace) { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); double width = extent.End.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; textBounds.Add(new TextBounds(line.TextRight, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); } AddGeometries(textView, textBounds, isMultiLine, clipToViewport, padding, SystemParameters.CaretWidth, ref geo, ref createOutlinedPath); } } if (createOutlinedPath) { geo = geo.GetOutlinedPathGeometry(); } if (geo != null && geo.CanFreeze) { geo.Freeze(); } return(geo); }
List <MarkedLineInfo> GetMarkedLineInfos(List <MarkedLineInfo> infos, VirtualSnapshotSpan markedSpan) { infos.Clear(); var formattedSpan = textView.TextViewLines.FormattedSpan; bool useVspace = formattedSpan.End == markedSpan.End.Position && markedSpan.End.Position.Position == markedSpan.Snapshot.Length; var virtFormattedSpan = new VirtualSnapshotSpan(new VirtualSnapshotPoint(formattedSpan.Start), new VirtualSnapshotPoint(formattedSpan.End, useVspace ? markedSpan.End.VirtualSpaces : 0)); var intersectionTmp = virtFormattedSpan.Intersection(markedSpan); if (intersectionTmp == null) { return(infos); } var span = intersectionTmp.Value; bool isMultiLineSpan = MarkerHelper.IsMultiLineSpan(textView, span.SnapshotSpan); var pos = span.Start; int lines = 0; while (pos <= span.End) { if (lines > 0 && pos == span.End) { break; } var line = textView.TextViewLines.GetTextViewLineContainingBufferPosition(pos.Position); if (line == null) { break; } bool useVspace2 = useVspace && line.IsLastDocumentLine(); var lineSpan = new VirtualSnapshotSpan(new VirtualSnapshotPoint(line.Start), new VirtualSnapshotPoint(line.EndIncludingLineBreak, useVspace2 ? markedSpan.End.VirtualSpaces : 0)); var lineIntersectionTmp = lineSpan.Intersection(span); Debug.Assert(lineIntersectionTmp != null); if (lineIntersectionTmp != null) { infos.Add(new MarkedLineInfo(line, lineIntersectionTmp.Value, isMultiLineSpan)); } if (line.IsLastDocumentLine()) { break; } pos = new VirtualSnapshotPoint(line.EndIncludingLineBreak); lines++; } return(infos); }
public static Geometry CreateGeometry(IWpfTextView textView, VirtualSnapshotSpan span, bool isMultiLine, bool clipToViewport = false) { var padding = isMultiLine ? LineMarkerPadding : TextMarkerPadding; var pos = span.Start; PathGeometry geo = null; bool createOutlinedPath = false; while (pos <= span.End) { var line = textView.GetTextViewLineContainingBufferPosition(pos.Position); bool useVspaces = line.IsLastDocumentLine(); var lineExtent = new VirtualSnapshotSpan(new VirtualSnapshotPoint(line.Start), new VirtualSnapshotPoint(line.EndIncludingLineBreak, useVspaces ? span.End.VirtualSpaces : 0)); var extentTmp = lineExtent.Intersection(new VirtualSnapshotSpan(pos, span.End)); Debug.Assert(extentTmp != null); if (line.VisibilityState != VisibilityState.Unattached && extentTmp != null && extentTmp.Value.Length != 0) { var extent = extentTmp.Value; Collection<TextBounds> textBounds; if (extent.Start.IsInVirtualSpace) { var leading = line.TextRight + extent.Start.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; double width = line.EndOfLineWidth; int vspaces = span.End.VirtualSpaces - span.Start.VirtualSpaces; if (vspaces > 0) width = vspaces * textView.FormattedLineSource.ColumnWidth; textBounds = new Collection<TextBounds>(); textBounds.Add(new TextBounds(leading, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else if (extent.End.IsInVirtualSpace) { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); double width = extent.End.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; textBounds.Add(new TextBounds(line.TextRight, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); AddGeometries(textView, textBounds, isMultiLine, clipToViewport, padding, SystemParameters.CaretWidth, ref geo, ref createOutlinedPath); } if (line.IsLastDocumentLine()) break; pos = new VirtualSnapshotPoint(line.GetPointAfterLineBreak()); } if (createOutlinedPath) geo = geo.GetOutlinedPathGeometry(); if (geo != null && geo.CanFreeze) geo.Freeze(); return geo; }
void EnsureSpanVisibleX(VirtualSnapshotSpan span, EnsureSpanVisibleOptions options) { if ((textView.Options.WordWrapStyle() & WordWrapStyles.WordWrap) != 0) return; if (textView.ViewportWidth == 0) return; var lines = textView.TextViewLines.GetTextViewLinesIntersectingSpan(span.SnapshotSpan); if (lines.Count == 0) return; var ispan = span.Intersection(new VirtualSnapshotSpan(textView.TextViewLines.FormattedSpan)); if (ispan == null) return; span = ispan.Value; double left = double.PositiveInfinity, right = double.NegativeInfinity; for (int i = 0; i < lines.Count; i++) { var line = lines[i]; var lineSpan = line.ExtentIncludingLineBreak.Intersection(span.SnapshotSpan); if (lineSpan == null) continue; var startPoint = new VirtualSnapshotPoint(lineSpan.Value.Start); var endPoint = new VirtualSnapshotPoint(lineSpan.Value.End); if (startPoint.Position == span.Start.Position) startPoint = span.Start; if (endPoint.Position == span.End.Position) endPoint = span.End; var startBounds = line.GetExtendedCharacterBounds(startPoint); var endBounds = line.GetExtendedCharacterBounds(endPoint); if (left > startBounds.Left) left = startBounds.Left; if (right < startBounds.Right) right = startBounds.Right; if (left > endBounds.Left) left = endBounds.Left; if (right < endBounds.Right) right = endBounds.Right; } if (double.IsInfinity(left) || double.IsInfinity(right)) return; Debug.Assert(left <= right); if (left > right) right = left; double width = right - left; double availWidth = Math.Max(0, textView.ViewportWidth - width); double extraScroll; const double EXTRA_WIDTH = 4; if (availWidth >= EXTRA_WIDTH) extraScroll = EXTRA_WIDTH; else extraScroll = availWidth / 2; if (textView.ViewportLeft <= right && right <= textView.ViewportRight) { } else if (right > textView.ViewportRight) textView.ViewportLeft = right + extraScroll - textView.ViewportWidth; else { var newLeft = left - extraScroll; if (newLeft + textView.ViewportWidth < right) newLeft = right - textView.ViewportWidth; textView.ViewportLeft = newLeft; } }
public static Geometry CreateGeometry(IWpfTextView textView, VirtualSnapshotSpan span, bool isBoxMode, bool isMultiLine, bool extraPixelsHack, bool clipToViewport = false, int maxLines = 1) { // Force multiline mode if it's box selection or there'll be 1px-sized non-selected lines // between the lines if you zoom in (eg. 110% zoom level) if (isBoxMode) { isMultiLine = true; } var padding = isMultiLine ? LineMarkerPadding : TextMarkerPadding; var pos = span.Start; PathGeometry geo = null; bool createOutlinedPath = false; int lines = 0; while (pos <= span.End && lines < maxLines) { var line = textView.GetTextViewLineContainingBufferPosition(pos.Position); bool useVspaces = line.IsLastDocumentLine() || lines + 1 == maxLines; var lineExtent = new VirtualSnapshotSpan(new VirtualSnapshotPoint(line.Start), new VirtualSnapshotPoint(line.EndIncludingLineBreak, useVspaces ? span.End.VirtualSpaces : 0)); var extentTmp = lineExtent.Intersection(new VirtualSnapshotSpan(pos, span.End)); Debug.Assert(extentTmp != null); if (extentTmp != null) { var extent = extentTmp.Value; Collection <TextBounds> textBounds; if (extent.Start.IsInVirtualSpace) { var leading = line.TextRight + extent.Start.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; double width = isBoxMode ? 0 : line.EndOfLineWidth; int vspaces = span.End.VirtualSpaces - span.Start.VirtualSpaces; if (vspaces > 0) { width = vspaces * textView.FormattedLineSource.ColumnWidth; } textBounds = new Collection <TextBounds>(); textBounds.Add(new TextBounds(leading, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else if (extent.End.IsInVirtualSpace) { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); double width = extent.End.VirtualSpaces * textView.FormattedLineSource.ColumnWidth; textBounds.Add(new TextBounds(line.TextRight, line.Top, width, line.Height, line.TextTop, line.TextHeight)); } else { textBounds = line.GetNormalizedTextBounds(extent.SnapshotSpan); } AddGeometries(textView, textBounds, isMultiLine, clipToViewport, padding, SystemParameters.CaretWidth, ref geo, ref createOutlinedPath, extraPixelsHack); } if (line.IsLastDocumentLine()) { break; } pos = new VirtualSnapshotPoint(line.GetPointAfterLineBreak()); lines++; } if (createOutlinedPath) { geo = geo.GetOutlinedPathGeometry(); } if (geo != null && geo.CanFreeze) { geo.Freeze(); } return(geo); }
void EnsureSpanVisibleX(VirtualSnapshotSpan span, EnsureSpanVisibleOptions options) { if ((textView.Options.WordWrapStyle() & WordWrapStyles.WordWrap) != 0) { return; } if (textView.ViewportWidth == 0) { return; } var lines = textView.TextViewLines.GetTextViewLinesIntersectingSpan(span.SnapshotSpan); if (lines.Count == 0) { return; } var ispan = span.Intersection(new VirtualSnapshotSpan(textView.TextViewLines.FormattedSpan)); if (ispan == null) { return; } span = ispan.Value; double left = double.PositiveInfinity, right = double.NegativeInfinity; for (int i = 0; i < lines.Count; i++) { var line = lines[i]; var lineSpan = line.ExtentIncludingLineBreak.Intersection(span.SnapshotSpan); if (lineSpan == null) { continue; } var startPoint = new VirtualSnapshotPoint(lineSpan.Value.Start); var endPoint = new VirtualSnapshotPoint(lineSpan.Value.End); if (startPoint.Position == span.Start.Position) { startPoint = span.Start; } if (endPoint.Position == span.End.Position) { endPoint = span.End; } var startBounds = line.GetExtendedCharacterBounds(startPoint); var endBounds = line.GetExtendedCharacterBounds(endPoint); if (left > startBounds.Left) { left = startBounds.Left; } if (right < startBounds.Right) { right = startBounds.Right; } if (left > endBounds.Left) { left = endBounds.Left; } if (right < endBounds.Right) { right = endBounds.Right; } } if (double.IsInfinity(left) || double.IsInfinity(right)) { return; } Debug.Assert(left <= right); if (left > right) { right = left; } double width = right - left; double availWidth = Math.Max(0, textView.ViewportWidth - width); double extraScroll; const double EXTRA_WIDTH = 4; if (availWidth >= EXTRA_WIDTH) { extraScroll = EXTRA_WIDTH; } else { extraScroll = availWidth / 2; } if (textView.ViewportLeft <= right && right <= textView.ViewportRight) { } else if (right > textView.ViewportRight) { textView.ViewportLeft = right + extraScroll - textView.ViewportWidth; } else { var newLeft = left - extraScroll; if (newLeft + textView.ViewportWidth < right) { newLeft = right - textView.ViewportWidth; } textView.ViewportLeft = newLeft; } }