Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 8d201c3

Browse files
committed
Merge pull request #187 from github/shana/new-menu-system
New menu handling system
2 parents e4cf04c + 0b6ccb2 commit 8d201c3

11 files changed

+179
-21
lines changed

src/GitHub.Exports/GitHub.Exports.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@
112112
<Compile Include="Services\Connection.cs" />
113113
<Compile Include="Services\GitService.cs" />
114114
<Compile Include="Services\IGitService.cs" />
115+
<Compile Include="Services\IMenuHandler.cs" />
116+
<Compile Include="Services\IMenuProvider.cs" />
115117
<Compile Include="Services\ITeamExplorerServiceHolder.cs" />
116118
<Compile Include="Services\Logger.cs" />
117119
<Compile Include="Services\Services.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System;
2+
3+
namespace GitHub.VisualStudio
4+
{
5+
/// <summary>
6+
/// Interface for MEF exports implementing menu handlers
7+
/// (top level context, toolbar, etc)
8+
/// </summary>
9+
public interface IMenuHandler
10+
{
11+
Guid Guid { get; }
12+
int CmdId { get; }
13+
void Activate();
14+
}
15+
16+
/// <summary>
17+
/// Interface for MEF exports implementing menu handlers
18+
/// (top level context, toolbar, etc)
19+
/// Allows hiding the menu (requires vsct visibility flags)
20+
/// </summary>
21+
public interface IDynamicMenuHandler : IMenuHandler
22+
{
23+
bool CanShow();
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace GitHub.VisualStudio
5+
{
6+
/// <summary>
7+
/// Container for static and dynamic visibility menus (context, toolbar, top, etc)
8+
/// Get a reference to this via MEF and register the menus
9+
/// </summary>
10+
public interface IMenuProvider
11+
{
12+
/// <summary>
13+
/// Registered via AddTopLevelMenuItem
14+
/// </summary>
15+
IReadOnlyCollection<IMenuHandler> Menus { get; }
16+
17+
/// <summary>
18+
/// Registered via AddDynamicMenuItem
19+
/// </summary>
20+
IReadOnlyCollection<IDynamicMenuHandler> DynamicMenus { get; }
21+
}
22+
}

src/GitHub.Exports/Services/Services.cs

+2
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ public static IVsOutputWindowPane OutputWindowPane
8181
// ReSharper disable once SuspiciousTypeConversion.Global
8282
public static DTE2 Dte2 => Dte as DTE2;
8383

84+
public static IVsUIShell UIShell => GetGlobalService<SVsUIShell, IVsUIShell>();
85+
8486
public static IVsActivityLog GetActivityLog(this IServiceProvider provider)
8587
{
8688
return GetGlobalService<SVsActivityLog, IVsActivityLog>(provider);
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
3+
namespace GitHub.VisualStudio
4+
{
5+
public abstract class MenuBase
6+
{
7+
readonly IServiceProvider serviceProvider;
8+
protected IServiceProvider ServiceProvider { get { return serviceProvider; } }
9+
10+
protected MenuBase()
11+
{
12+
}
13+
14+
protected MenuBase(IServiceProvider serviceProvider)
15+
{
16+
this.serviceProvider = serviceProvider;
17+
}
18+
}
19+
}

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

+5-3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<StartArguments>/rootsuffix Exp</StartArguments>
2828
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
2929
<ZipPackageCompressionLevel>Normal</ZipPackageCompressionLevel>
30+
<OutputPath>..\..\build\$(Configuration)\</OutputPath>
3031
</PropertyGroup>
3132
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
3233
<DebugSymbols>true</DebugSymbols>
@@ -39,7 +40,6 @@
3940
<CodeAnalysisRuleSet>..\common\GitHubVS.ruleset</CodeAnalysisRuleSet>
4041
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
4142
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
42-
<OutputPath>..\..\build\$(Configuration)\</OutputPath>
4343
<CreateVsixContainer>True</CreateVsixContainer>
4444
<DeployExtension>True</DeployExtension>
4545
<IncludeDebugSymbolsInVSIXContainer>true</IncludeDebugSymbolsInVSIXContainer>
@@ -54,7 +54,6 @@
5454
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
5555
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
5656
<CodeAnalysisRuleSet>..\common\GitHubVS.ruleset</CodeAnalysisRuleSet>
57-
<OutputPath>..\..\build\$(Configuration)\</OutputPath>
5857
<IncludeDebugSymbolsInVSIXContainer>true</IncludeDebugSymbolsInVSIXContainer>
5958
</PropertyGroup>
6059
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Publish|AnyCPU' ">
@@ -67,7 +66,6 @@
6766
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
6867
<CodeAnalysisIgnoreGeneratedCode>true</CodeAnalysisIgnoreGeneratedCode>
6968
<CodeAnalysisRuleSet>..\common\GitHubVS.ruleset</CodeAnalysisRuleSet>
70-
<OutputPath>..\..\build\Release\</OutputPath>
7169
<DeployExtension>False</DeployExtension>
7270
</PropertyGroup>
7371
<PropertyGroup Condition="$(Buildtype) == 'Internal'">
@@ -214,6 +212,10 @@
214212
<Compile Include="Base\TeamExplorerServiceHolder.cs" />
215213
<Compile Include="Converters\CountToVisibilityConverter.cs" />
216214
<Compile Include="Helpers\SharedDictionaryManager.cs" />
215+
<Compile Include="Menus\ShowGitHubPane.cs" />
216+
<Compile Include="Menus\AddConnection.cs" />
217+
<Compile Include="Base\MenuBase.cs" />
218+
<Compile Include="Menus\MenuProvider.cs" />
217219
<Compile Include="Properties\AssemblyInfo.cs" />
218220
<Compile Include="Base\TeamExplorerBase.cs" />
219221
<Compile Include="Base\TeamExplorerItemBase.cs" />

src/GitHub.VisualStudio/GitHubPackage.cs

+7-17
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,19 @@ public GitHubPackage()
4242
public GitHubPackage(IServiceProvider serviceProvider)
4343
: base(serviceProvider)
4444
{
45-
4645
}
4746

47+
4848
protected override void Initialize()
4949
{
50-
51-
ServiceProvider.AddTopLevelMenuItem(GuidList.guidGitHubCmdSet, PkgCmdIDList.addConnectionCommand, (s, e) => StartFlow(UIControllerFlow.Authentication));
52-
ServiceProvider.AddTopLevelMenuItem(GuidList.guidGitHubCmdSet, PkgCmdIDList.showGitHubPaneCommand, (s, e) =>
53-
{
54-
var window = FindToolWindow(typeof(GitHubPane), 0, true);
55-
if (window?.Frame == null)
56-
throw new NotSupportedException("Cannot create tool window");
57-
58-
var windowFrame = (IVsWindowFrame)window.Frame;
59-
ErrorHandler.ThrowOnFailure(windowFrame.Show());
60-
});
6150
base.Initialize();
62-
}
6351

64-
void StartFlow(UIControllerFlow controllerFlow)
65-
{
66-
var uiProvider = ServiceProvider.GetExportedValue<IUIProvider>();
67-
uiProvider.RunUI(controllerFlow, null);
52+
var menus = ServiceProvider.GetExportedValue<IMenuProvider>();
53+
foreach (var menu in menus.Menus)
54+
ServiceProvider.AddTopLevelMenuItem(menu.Guid, menu.CmdId, (s, e) => menu.Activate());
55+
56+
foreach (var menu in menus.DynamicMenus)
57+
ServiceProvider.AddDynamicMenuItem(menu.Guid, menu.CmdId, menu.CanShow, menu.Activate);
6858
}
6959
}
7060
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using Microsoft.VisualStudio.Shell;
2+
using System;
3+
using System.ComponentModel.Composition;
4+
using GitHub.Services;
5+
using GitHub.UI;
6+
using GitHub.Extensions;
7+
8+
namespace GitHub.VisualStudio.Menus
9+
{
10+
[Export(typeof(IMenuHandler))]
11+
[PartCreationPolicy(CreationPolicy.Shared)]
12+
public class AddConnection: MenuBase, IMenuHandler
13+
{
14+
[ImportingConstructor]
15+
public AddConnection([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider)
16+
: base(serviceProvider)
17+
{
18+
}
19+
20+
public Guid Guid { get { return GuidList.guidGitHubCmdSet; } }
21+
public int CmdId { get { return PkgCmdIDList.addConnectionCommand; } }
22+
23+
public void Activate()
24+
{
25+
StartFlow(UIControllerFlow.Authentication);
26+
}
27+
28+
void StartFlow(UIControllerFlow controllerFlow)
29+
{
30+
var uiProvider = ServiceProvider.GetExportedValue<IUIProvider>();
31+
uiProvider.RunUI(controllerFlow, null);
32+
}
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Collections.Generic;
2+
using System.Collections.ObjectModel;
3+
using System.ComponentModel.Composition;
4+
using System.Linq;
5+
6+
namespace GitHub.VisualStudio.Menus
7+
{
8+
[Export(typeof(IMenuProvider))]
9+
[PartCreationPolicy(CreationPolicy.Shared)]
10+
public class MenuProvider : IMenuProvider
11+
{
12+
public IReadOnlyCollection<IMenuHandler> Menus { get; private set; }
13+
14+
public IReadOnlyCollection<IDynamicMenuHandler> DynamicMenus { get; private set; }
15+
16+
[ImportingConstructor]
17+
public MenuProvider([ImportMany] IEnumerable<IMenuHandler> menus, [ImportMany] IEnumerable<IDynamicMenuHandler> dynamicMenus)
18+
{
19+
Menus = new ReadOnlyCollection<IMenuHandler>(menus.ToList());
20+
DynamicMenus = new ReadOnlyCollection<IDynamicMenuHandler>(dynamicMenus.ToList());
21+
}
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using GitHub.VisualStudio.UI;
2+
using System;
3+
using System.ComponentModel.Composition;
4+
5+
namespace GitHub.VisualStudio
6+
{
7+
[Export(typeof(IMenuHandler))]
8+
[PartCreationPolicy(CreationPolicy.Shared)]
9+
public class ShowGitHubPane: MenuBase, IMenuHandler
10+
{
11+
public Guid Guid { get { return GuidList.guidGitHubCmdSet; } }
12+
public int CmdId { get { return PkgCmdIDList.showGitHubPaneCommand; } }
13+
14+
public void Activate()
15+
{
16+
GitHubPane.Activate();
17+
}
18+
}
19+
}

src/GitHub.VisualStudio/UI/GitHubPane.cs

+21-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using GitHub.VisualStudio.Base;
1212
using GitHub.ViewModels;
1313
using System.Diagnostics;
14+
using Microsoft.VisualStudio;
1415

1516
namespace GitHub.VisualStudio.UI
1617
{
@@ -26,9 +27,11 @@ namespace GitHub.VisualStudio.UI
2627
/// implementation of the IVsUIElementPane interface.
2728
/// </para>
2829
/// </remarks>
29-
[Guid("6b0fdc0a-f28e-47a0-8eed-cc296beff6d2")]
30+
[Guid(GitHubPaneGuid)]
3031
public class GitHubPane : ToolWindowPane
3132
{
33+
const string GitHubPaneGuid = "6b0fdc0a-f28e-47a0-8eed-cc296beff6d2";
34+
3235
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
3336
public GitHubPane() : base(null)
3437
{
@@ -57,5 +60,22 @@ protected override void Initialize()
5760
Debug.Assert(vm != null);
5861
vm?.Initialize(this);
5962
}
63+
64+
public static bool Activate()
65+
{
66+
var windowGuid = new Guid(GitHubPaneGuid);
67+
IVsWindowFrame frame;
68+
if (ErrorHandler.Failed(Services.UIShell.FindToolWindow((uint)__VSCREATETOOLWIN.CTW_fForceCreate, ref windowGuid, out frame)))
69+
{
70+
VsOutputLogger.WriteLine("Unable to find or create GitHubPane '" + GitHubPaneGuid + "'");
71+
return false;
72+
}
73+
if (ErrorHandler.Failed(frame.Show()))
74+
{
75+
VsOutputLogger.WriteLine("Unable to show GitHubPane '" + GitHubPaneGuid + "'");
76+
return false;
77+
}
78+
return true;
79+
}
6080
}
6181
}

0 commit comments

Comments
 (0)