Skip to content

Commit

Permalink
Added the ability to get a WindowFrame wrapper for a tool window's fr…
Browse files Browse the repository at this point in the history
…ame.
  • Loading branch information
reduckted committed Jun 3, 2023
1 parent daf6122 commit ae29085
Showing 1 changed file with 70 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;

namespace Community.VisualStudio.Toolkit
{
Expand All @@ -10,6 +11,8 @@ namespace Community.VisualStudio.Toolkit
public abstract class ToolkitToolWindowPane : ToolWindowPane
{
private bool _isInitialized;
private WindowFrame? _windowFrame;
private bool _isWindowFrameAvailable;

/// <inheritdoc/>
protected override void Initialize()
Expand All @@ -22,5 +25,72 @@ protected override void Initialize()
internal bool IsInitialized => _isInitialized;

internal event EventHandler? Initialized;

/// <inheritdoc/>
public override void OnToolWindowCreated()
{
base.OnToolWindowCreated();
_isWindowFrameAvailable = true;
WindowFrameAvailable?.Invoke(this, EventArgs.Empty);
}

/// <summary>
/// Indicates whether the <see cref="GetWindowFrame"/> method can be called.
/// </summary>
public bool IsWindowFrameAvailable => _isWindowFrameAvailable;

/// <summary>
/// Raised when Visual Studio creates the tool window's frame.
/// The <see cref="WindowFrame"/> property can be accessed from this point onwards.
/// </summary>
public event EventHandler? WindowFrameAvailable;

/// <summary>
/// Gets the tool window's window frame.
/// <para>
/// This method can only be called after Visual Studio has created the window frame.
/// You can detect this in various ways:
/// <list type="bullet">
/// <item>
/// Override the <see cref="OnToolWindowCreated"/> method.
/// When this method is called, the window frame will be available.
/// </item>
/// <item>
/// Listen for the <see cref="WindowFrameAvailable"/> event.
/// When the event is raised, the window frame will be available.
/// </item>
/// <item>
/// Check the <see cref="IsWindowFrameAvailable"/> property.
/// </item>
/// </list>
/// </para>
/// </summary>
/// <exception cref="InvalidOperationException">The window frame is not available.</exception>
protected WindowFrame GetWindowFrame()
{
if (_windowFrame is null)
{
// The `Frame` property has to be set by Visual Studio, so it might
// be null at this point. It's also typed as an `object` even though
// internally it's stored as an `IVsWindowFrame`, so we can use
// type matching to both cast and confirm that it's not null.
if (Frame is IVsWindowFrame vsWindowFrame)
{
// We could create the WindowFrame in `OnToolWindowCreated`,
// but we delay-create it for two reasons:
// 1. It may not ever be needed.
// 2. If a derived class also overrides `OnToolWindowCreated`, then the window
// frame would only be available after it called `base.OnToolWindowCreated()`.
// Delay-creating it means that it will be available before that call is made.
_windowFrame = new WindowFrame(vsWindowFrame);
}
else
{
throw new InvalidOperationException("The tool window's frame is not available yet.");
}
}

return _windowFrame;
}
}
}

0 comments on commit ae29085

Please sign in to comment.