|
// 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 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();
}
}
}
|