File: ViewHostingControl.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.
 
#nullable disable
 
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Projection;
 
namespace Microsoft.CodeAnalysis.Editor.Shared.Utilities;
 
internal sealed class ViewHostingControl : ContentControl
{
    private readonly Func<ITextBuffer, IWpfTextView> _createView;
    private readonly Func<ITextBuffer> _createBuffer;
 
    private ITextBuffer _createdTextBuffer;
    private IWpfTextView _createdView;
 
    public ViewHostingControl(
        Func<ITextBuffer, IWpfTextView> createView,
        Func<ITextBuffer> createBuffer)
    {
        _createView = createView;
        _createBuffer = createBuffer;
 
        Background = Brushes.Transparent;
        this.IsVisibleChanged += OnIsVisibleChanged;
    }
 
    private void EnsureBufferCreated()
    {
        _createdTextBuffer ??= _createBuffer();
    }
 
    private void EnsureContentCreated()
    {
        if (this.Content == null)
        {
            EnsureBufferCreated();
            _createdView = _createView(_createdTextBuffer);
            this.Content = _createdView.VisualElement;
        }
    }
 
    public ITextView TextView_TestOnly
    {
        get
        {
            EnsureContentCreated();
            return (ITextView)this.Content;
        }
    }
 
    private void OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var nowVisible = (bool)e.NewValue;
        if (nowVisible)
        {
            EnsureContentCreated();
        }
        else
        {
            this.Content = null;
 
            _createdView.Close();
            _createdView = null;
 
            // If a projection buffer has a source span from another buffer, the projection buffer is held alive by the other buffer too.
            // This means that a one-off projection buffer created for a tooltip would be kept alive as long as the underlying file
            // is still open. Removing the source spans from the projection buffer ensures the projection buffer can be GC'ed.
            if (_createdTextBuffer is IProjectionBuffer projectionBuffer)
            {
                projectionBuffer.DeleteSpans(0, projectionBuffer.CurrentSnapshot.SpanCount);
            }
 
            _createdTextBuffer = null;
        }
    }
 
    public string GetText_TestOnly()
    {
        EnsureBufferCreated();
        return _createdTextBuffer.CurrentSnapshot.GetText();
    }
}