public ITextAndAdornmentCollection CreateTextAndAdornmentCollection(SnapshotSpan topSpan, ITextSnapshot sourceTextSnapshot)
        {
            if (topSpan.Snapshot is null)
            {
                throw new ArgumentException();
            }
            if (sourceTextSnapshot is null)
            {
                throw new ArgumentNullException(nameof(sourceTextSnapshot));
            }
            if (topSpan.Snapshot.TextBuffer != TopBuffer)
            {
                throw new InvalidOperationException();
            }
            if (sourceTextSnapshot.TextBuffer != SourceBuffer)
            {
                throw new InvalidOperationException();
            }

            if (SourceBuffer != TopBuffer)
            {
                throw new NotSupportedException();
            }

            List <AdornmentElementAndSpan>?adornmentList = null;

            foreach (var tagSpan in tagAggregator.GetTags(topSpan))
            {
                if (adornmentList is null)
                {
                    adornmentList = new List <AdornmentElementAndSpan>();
                }
                var spans = tagSpan.Span.GetSpans(sourceTextSnapshot);
                Debug.Assert(spans.Count == 1);
                if (spans.Count != 1)
                {
                    continue;
                }
                adornmentList.Add(new AdornmentElementAndSpan(new AdornmentElement(tagSpan), spans[0]));
            }

            // Common case
            if (adornmentList is null)
            {
                var elem = new TextSequenceElement(BufferGraph.CreateMappingSpan(topSpan, SpanTrackingMode.EdgeExclusive));
                return(new TextAndAdornmentCollection(this, new[] { elem }));
            }

            var sequenceList = new List <ISequenceElement>();

            adornmentList.Sort(AdornmentElementAndSpanComparer.Instance);
            int start = topSpan.Start;
            int end   = topSpan.End;
            int curr  = start;
            AdornmentElementAndSpan?lastAddedAdornment = null;

            for (int i = 0; i < adornmentList.Count; i++)
            {
                var info      = adornmentList[i];
                int spanStart = info.Span.Length == 0 && info.AdornmentElement.Affinity == PositionAffinity.Predecessor ? info.Span.Start - 1 : info.Span.Start;
                if (spanStart < start)
                {
                    continue;
                }
                if (info.Span.Start > end)
                {
                    break;
                }
                var textSpan = new SnapshotSpan(topSpan.Snapshot, Span.FromBounds(curr, info.Span.Start));
                if (!textSpan.IsEmpty)
                {
                    sequenceList.Add(new TextSequenceElement(BufferGraph.CreateMappingSpan(textSpan, SpanTrackingMode.EdgeExclusive)));
                }
                if (info.Span.Start != end || (info.Span.Length == 0 && info.AdornmentElement.Affinity == PositionAffinity.Predecessor))
                {
                    bool canAppend = true;
                    if (!(lastAddedAdornment is null) && lastAddedAdornment.Value.Span.End > info.Span.Start)
                    {
                        canAppend = false;
                    }
                    if (canAppend)
                    {
                        sequenceList.Add(info.AdornmentElement);
                        lastAddedAdornment = info;
                    }
                }
                curr = info.Span.End;
            }
            if (curr < end)
            {
                var textSpan = new SnapshotSpan(topSpan.Snapshot, Span.FromBounds(curr, end));
                Debug.Assert(!textSpan.IsEmpty);
                sequenceList.Add(new TextSequenceElement(BufferGraph.CreateMappingSpan(textSpan, SpanTrackingMode.EdgeExclusive)));
            }

            return(new TextAndAdornmentCollection(this, sequenceList));
        }
Exemple #2
0
        public override HexAndAdornmentCollection CreateHexAndAdornmentCollection(HexBufferLine line)
        {
            if (line == null)
            {
                throw new ArgumentNullException(nameof(line));
            }
            if (line.Buffer != hexView.Buffer)
            {
                throw new ArgumentException();
            }
            var lineSpan = line.TextSpan;

            List <AdornmentElementAndSpan> adornmentList = null;

            foreach (var tagSpan in hexTagAggregator.GetAllTags(new HexTaggerContext(line, lineSpan)))
            {
                if (adornmentList == null)
                {
                    adornmentList = new List <AdornmentElementAndSpan>();
                }
                adornmentList.Add(new AdornmentElementAndSpan(new HexAdornmentElementImpl(tagSpan), tagSpan.Span));
            }

            // Common case
            if (adornmentList == null)
            {
                var elem = new HexSequenceElementImpl(lineSpan);
                return(new HexAndAdornmentCollectionImpl(this, new[] { elem }));
            }

            var sequenceList = new List <HexSequenceElement>();

            adornmentList.Sort(AdornmentElementAndSpanComparer.Instance);
            int start = lineSpan.Start;
            int end   = lineSpan.End;
            int curr  = start;
            AdornmentElementAndSpan?lastAddedAdornment = null;

            for (int i = 0; i < adornmentList.Count; i++)
            {
                var info      = adornmentList[i];
                int spanStart = info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor ? info.Span.Start - 1 : info.Span.Start;
                if (spanStart < start)
                {
                    continue;
                }
                if (info.Span.Start > end)
                {
                    break;
                }
                var textSpan = VST.Span.FromBounds(curr, info.Span.Start);
                if (!textSpan.IsEmpty)
                {
                    sequenceList.Add(new HexSequenceElementImpl(textSpan));
                }
                if (info.Span.Start != end || (info.Span.Length == 0 && info.AdornmentElement.Affinity == VST.PositionAffinity.Predecessor))
                {
                    bool canAppend = true;
                    if (lastAddedAdornment != null && lastAddedAdornment.Value.Span.End > info.Span.Start)
                    {
                        canAppend = false;
                    }
                    if (canAppend)
                    {
                        sequenceList.Add(info.AdornmentElement);
                        lastAddedAdornment = info;
                    }
                }
                curr = info.Span.End;
            }
            if (curr < end)
            {
                var textSpan = VST.Span.FromBounds(curr, end);
                Debug.Assert(!textSpan.IsEmpty);
                sequenceList.Add(new HexSequenceElementImpl(textSpan));
            }

            return(new HexAndAdornmentCollectionImpl(this, sequenceList.ToArray()));
        }