Skip to content

Commit

Permalink
Merge pull request #340 from reduckted/feature/tool-window-pane-aware
Browse files Browse the repository at this point in the history
Allowed a tool window or its content to get access to the ToolWindowPane
  • Loading branch information
madskristensen authored May 25, 2022
2 parents 97e1577 + 85f3f7c commit c71e69b
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 3 deletions.
2 changes: 1 addition & 1 deletion demo/VSSDK.TestExtension/ToolWindows/RunnerWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public override async Task<FrameworkElement> CreateAsync(int toolWindowId, Cance
}

[Guid("d3b3ebd9-87d1-41cd-bf84-268d88953417")]
internal class Pane : ToolWindowPane
internal class Pane : ToolkitToolWindowPane
{
public Pane()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
using Community.VisualStudio.Toolkit;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

namespace TestExtension
{
public partial class RunnerWindowControl : UserControl
public partial class RunnerWindowControl : UserControl, IToolWindowPaneAware
{
public RunnerWindowControl(Version vsVersion, RunnerWindowMessenger messenger)
{
Expand Down Expand Up @@ -55,5 +56,10 @@ private async Task HideAsync()
{
await RunnerWindow.HideAsync();
}

public void SetPane(ToolWindowPane pane)
{
MessageList.Items.Add("Pane has been set.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ protected override WindowPane InstantiateToolWindow(Type toolWindowType, object
toolPane.Caption = provider.GetTitle(data.Id);
}

// Now we can try to give the pane object to the tool window implementation and the content
// if they want to know about the pane. At this point the pane has probably not been initialized,
// and if it hasn't, then it won't be initialized until some time after we return from this method.
// We could given the pane to the tool window implementation, but you can't use the pane until it has
// been initialized, and there's no way to know when it has been initialized unless you implement your
// own logic in your ToolWindowPane implementation. To provide a better user experience, if your tool
// window needs access to the window pane, then we will require that the pane inherit from our custom
// `ToolkitWindowPane` class. This implementation allows us to detect if and when the pane is initialized.
// Once the pane has been initialized, we can given the pane to the tool window and its content.
if (pane is ToolkitToolWindowPane toolkitPane)
{
ProvidePaneToToolWindow(toolkitPane, data.Id, provider);
}

return pane;
}
else
Expand All @@ -97,6 +111,24 @@ protected override WindowPane InstantiateToolWindow(Type toolWindowType, object
}
}

private void ProvidePaneToToolWindow(ToolkitToolWindowPane pane, int toolWindowId, IToolWindowProvider provider)
{
if (pane.IsInitialized)
{
OnInitialized(pane, EventArgs.Empty);
}
else
{
pane.Initialized += OnInitialized;
}

void OnInitialized(object s, EventArgs e)
{
provider.SetPane(pane, toolWindowId);
(pane.Content as IToolWindowPaneAware)?.SetPane(pane);
}
}

private class InstantiateToolWindowData
{
public InstantiateToolWindowData(int id, FrameworkElement content)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Debugger\Debugger.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Windows\IToolWindowPaneAware.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Windows\ToolkitToolWindowPane.cs" />
<Compile Include="$(MSBuildThisFileDirectory)\Attributes\ProvideBraceCompletionAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)\Attributes\ProvideFileIconAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)\Attributes\ProvideGalleryFeedAttribute.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace Community.VisualStudio.Toolkit
/// }
///
/// [Guid("d0050678-2e4f-4a93-adcb-af1370da941d")]
/// internal class Pane : ToolWindowPane
/// internal class Pane : ToolkitToolWindowPane
/// {
/// public Pane()
/// {
Expand Down Expand Up @@ -164,5 +164,16 @@ public static async Task<bool> HideAsync(int id = 0)
/// <param name="cancellationToken">The cancellation token to use when performing asynchronous operations.</param>
/// <returns>The UI element to show in the tool window.</returns>
public abstract Task<FrameworkElement> CreateAsync(int toolWindowId, CancellationToken cancellationToken);

/// <summary>
/// Called when the <see cref="ToolWindowPane"/> has been initialized and "sited".
/// The pane's service provider can be used from this point onwards.
/// </summary>
/// <param name="pane">The tool window pane that was created.</param>
/// <param name="toolWindowId">The ID of the tool window that the pane belongs to.</param>
public virtual void SetPane(ToolWindowPane pane, int toolWindowId)
{
// Consumers can override this if they need access to the pane.
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.VisualStudio.Shell;

namespace Community.VisualStudio.Toolkit
{
/// <summary>
/// Allows the content of a <see cref="ToolWindowPane"/> to be aware of its owning <see cref="ToolWindowPane"/> object.
/// <para>
/// Implement this interface on your tool window's content (the object you return from
/// <see cref="BaseToolWindow{T}.CreateAsync(int, System.Threading.CancellationToken)"/>)
/// if you need the content object to have access to its <see cref="ToolWindowPane"/>.
/// </para>
/// </summary>
public interface IToolWindowPaneAware
{
/// <summary>
/// Called when the <see cref="ToolWindowPane"/> has been initialized and "sited".
/// The pane's service provider can be used from this point onwards.
/// </summary>
/// <param name="pane">The tool window pane that was created.</param>
void SetPane(ToolWindowPane pane);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.VisualStudio.Shell;

namespace Community.VisualStudio.Toolkit
{
Expand All @@ -12,5 +13,7 @@ internal interface IToolWindowProvider
public Type PaneType { get; }

public Task<FrameworkElement> CreateAsync(int toolWindowId, CancellationToken cancellationToken);

public void SetPane(ToolWindowPane pane, int toolWindowId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Microsoft.VisualStudio.Shell;

namespace Community.VisualStudio.Toolkit
{
/// <summary>
/// An implementation of <see cref="ToolWindowPane"/> that allows the
/// </summary>
public abstract class ToolkitToolWindowPane : ToolWindowPane
{
private bool _isInitialized;

/// <inheritdoc/>
protected override void Initialize()
{
base.Initialize();
_isInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}

internal bool IsInitialized => _isInitialized;

internal event EventHandler? Initialized;
}
}

0 comments on commit c71e69b

Please sign in to comment.