void AddLineElements(NormalizedSnapshotSpanCollection spans) { if (spans.Count == 0) { return; } var list = new List <StructureVisualizerData>(); var updated = new HashSet <StructureVisualizerData>(StructureVisualizerDataComparer.Instance); foreach (var span in spans) { list.Clear(); structureVisualizerServiceDataProvider.GetData(GetLineExtent(span), list); foreach (var info in list) { if (updated.Contains(info)) { continue; } updated.Add(info); var lineElement = FindLineElement(info); if (lineElement != null) { layer.RemoveAdornment(lineElement); Debug.Assert(!lineElements.Contains(lineElement)); } if (lineElement == null) { lineElement = new LineElement(info); } var lines = wpfTextView.TextViewLines.GetTextViewLinesIntersectingSpan(lineElement.Span); if (lines.Count == 0) { continue; } int lineStartIndex = 0; int lineEndIndex = lines.Count - 1; // Don't add a vertical line to the line containing the start or end block if (LineContainsSpan(info.Top, lines[lineStartIndex])) { lineStartIndex++; } if (LineContainsSpan(info.Bottom, lines[lineEndIndex])) { lineEndIndex--; } if (lineStartIndex > lineEndIndex) { continue; } double top = lines[lineStartIndex].Top; double bottom = lines[lineEndIndex].Bottom; if (bottom - top < 0.5) { continue; } double x = GetLineXPosition(info); var pen = GetPen(info.BlockKind); lineElement.Update(x, bottom, top, pen); bool added = layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, lineElement.Span, null, lineElement, onRemovedDelegate); if (added) { lineElements.Add(lineElement); } } } }
IEnumerable <LineElementData> GetLineElementData(NormalizedSnapshotSpanCollection spans) { if (spans.Count == 0) { yield break; } var snapshot = spans[0].Snapshot; ITextSnapshotLine snapshotLine = null; SnapshotSpan lineExtent; var prevLineExtent = default(SnapshotSpan); var list = new List <StructureVisualizerData>(); StructureVisualizerData[] listArray = null; List <ITextViewLine> linesList = null; foreach (var span in spans) { var lines = GetTextViewLinesIntersectingSpan(span, ref linesList); foreach (var line in lines) { if (snapshotLine != null) { if (line.Start >= snapshotLine.Start && line.EndIncludingLineBreak <= snapshotLine.EndIncludingLineBreak) { // Nothing } else if (line.Start == snapshotLine.EndIncludingLineBreak) { snapshotLine = snapshotLine.Snapshot.GetLineFromLineNumber(snapshotLine.LineNumber + 1); } else { snapshotLine = line.Start.GetContainingLine(); } lineExtent = snapshotLine.Extent; } else if (line.IsFirstTextViewLineForSnapshotLine && line.IsLastTextViewLineForSnapshotLine) { lineExtent = line.Extent; } else { snapshotLine = line.Start.GetContainingLine(); lineExtent = snapshotLine.Extent; } if (prevLineExtent != lineExtent) { list.Clear(); structureVisualizerServiceDataProvider.GetData(lineExtent, list); listArray = list.Count == 0 ? Array.Empty <StructureVisualizerData>() : list.ToArray(); } if (listArray.Length != 0) { var last = listArray[listArray.Length - 1]; // Don't add a vertical line to the line containing the start block if (!(last.Top.Start >= lineExtent.Start && last.Top.End <= lineExtent.End)) { var ary = listArray; if (last.Bottom.Start >= lineExtent.Start && last.Bottom.End <= lineExtent.End) { ary = new StructureVisualizerData[listArray.Length - 1]; for (int i = 0; i < ary.Length; i++) { ary[i] = listArray[i]; } } yield return(new LineElementData(line, ary)); } } prevLineExtent = lineExtent; } } }