File: LineSeparators\LineSeparatorAdornmentManager.cs
Web Access
Project: src\src\EditorFeatures\Core.Wpf\Microsoft.CodeAnalysis.EditorFeatures.Wpf_a0rtafw3_wpftmp.csproj (Microsoft.CodeAnalysis.EditorFeatures.Wpf)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using Microsoft.CodeAnalysis.Editor.Implementation.Adornments;
using Microsoft.CodeAnalysis.Editor.Implementation.LineSeparators;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
 
namespace Microsoft.CodeAnalysis.Editor.LineSeparators;
 
internal sealed class LineSeparatorAdornmentManager : AbstractAdornmentManager<LineSeparatorTag>
{
    public LineSeparatorAdornmentManager(IThreadingContext threadingContext, IWpfTextView textView,
        IViewTagAggregatorFactoryService tagAggregatorFactoryService, IAsynchronousOperationListener asyncListener, string adornmentLayerName)
        : base(threadingContext, textView, tagAggregatorFactoryService, asyncListener, adornmentLayerName)
    {
    }
 
    protected override void AddAdornmentsToAdornmentLayer_CallOnlyOnUIThread(NormalizedSnapshotSpanCollection changedSpanCollection)
    {
        // this method should only run on UI thread as we do WPF here.
        Contract.ThrowIfFalse(TextView.VisualElement.Dispatcher.CheckAccess());
 
        var viewSnapshot = TextView.TextSnapshot;
        var viewLines = TextView.TextViewLines;
 
        foreach (var changedSpan in changedSpanCollection)
        {
            // is there any effect on the view?
            if (!viewLines.IntersectsBufferSpan(changedSpan))
            {
                continue;
            }
 
            var tagSpans = TagAggregator.GetTags(changedSpan);
            foreach (var tagMappingSpan in tagSpans)
            {
                if (!TryGetMappedPoint(changedSpan, tagMappingSpan, out var mappedPoint))
                    continue;
 
                if (!TryGetViewLine(mappedPoint, out _))
                    continue;
 
                if (!ShouldDrawTag(tagMappingSpan))
                    continue;
 
                if (!TryMapToSingleSnapshotSpan(tagMappingSpan.Span, TextView.TextSnapshot, out var span))
                    continue;
 
                // add the visual to the adornment layer.
                var geometry = viewLines.GetMarkerGeometry(span);
                if (geometry != null)
                {
                    var tag = tagMappingSpan.Tag;
                    var graphicsResult = tag.GetGraphics(TextView, geometry, format: null);
                    AdornmentLayer.AddAdornment(
                        behavior: AdornmentPositioningBehavior.TextRelative,
                        visualSpan: span,
                        tag: tag,
                        adornment: graphicsResult.VisualElement,
                        removedCallback: delegate { graphicsResult.Dispose(); });
                }
            }
        }
    }
 
    protected override void RemoveAdornmentFromAdornmentLayer_CallOnlyOnUIThread(SnapshotSpan span)
    {
        AdornmentLayer.RemoveAdornmentsByVisualSpan(span);
    }
}