// VsPkg.cs : Implementation of FastForwardVisualStudio // using System; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.ComponentModel.Design; using Microsoft.Win32; using Microsoft.VisualStudio.Shell.Interop; using Microsoft.VisualStudio.OLE.Interop; using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio; using FastForward.WinCore.Configuration; using System.Collections.Generic; using FastForward.WinCore; namespace FastForward.VisualStudio { /// /// This is the class that implements the package exposed by this assembly. /// [PackageRegistration(UseManagedResourcesOnly = true)] [DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0")] [InstalledProductRegistration(true, null, null, null)] [ProvideLoadKey("Standard", "0.2", "FastForward.NET", "Craig Sutherland", 1)] [ProvideMenuResource(1000, 1)] [ProvideToolWindow(typeof(ProjectsToolWindow))] [Guid(GuidList.guidFastForwardVisualStudioPkgString)] public sealed class VisualStudioPackage : Package, IVsInstalledProduct { #region Private fields private VisualStudioConfig configuration; private ServerList servers = new ServerList(); #endregion #region Constructors /// /// Default constructor of the package. /// Inside this method you can place any initialization code that does not require /// any Visual Studio service because at this point the package object is created but /// not sited yet inside Visual Studio environment. The place to do all the other /// initialization is the Initialize method. /// public VisualStudioPackage() { System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString())); configuration = VisualStudioConfig.Load(); } #endregion #region Public properties #region Configuration /// /// Gets the configuration for the plug-in. /// public VisualStudioConfig Configuration { get { return this.configuration; } } #endregion #endregion #region Public methods #region IdBmpSplash() /// /// Gets the id for the splash screen bitmap. /// /// /// public int IdBmpSplash(out uint pIdBmp) { pIdBmp = 500; return VSConstants.S_OK; } #endregion #region IdIcoLogoForAboutbox() /// /// Gets the identifier of the icon for the about box. /// /// /// public int IdIcoLogoForAboutbox(out uint pIdIco) { pIdIco = 600; return VSConstants.S_OK; } #endregion #region OfficialName() /// /// Gets the official name of the plug-in. /// /// /// public int OfficialName(out string pbstrName) { pbstrName = "FastForward.NET"; return VSConstants.S_OK; } #endregion #region ProductDetails() /// /// Gets the product details. /// /// /// public int ProductDetails(out string pbstrProductDetails) { pbstrProductDetails = "Provides integration with CruiseControl.NET from within Visual Studio."; return VSConstants.S_OK; } #endregion #region ProductID() /// /// Gets the identifier of the product. /// /// /// public int ProductID(out string pbstrPID) { pbstrPID = "FastForward.VisualStudio"; return VSConstants.S_OK; } #endregion #endregion #region Protected methods #region Initialize() /// /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initilaization code that rely on services provided by VisualStudio. /// protected override void Initialize() { System.Diagnostics.Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); base.Initialize(); // Add our command handlers for menu (commands must exist in the .vsct file) OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; if (null != mcs) { // Create the command for the menu item. CommandID menuCommandID = new CommandID(GuidList.guidFastForwardVisualStudioCmdSet, (int)PkgCmdIDList.cmdidFfnetSettings); MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID); mcs.AddCommand(menuItem); // Create the command for the tool window CommandID toolwndCommandID = new CommandID(GuidList.guidFastForwardVisualStudioCmdSet, (int)PkgCmdIDList.cmdidProjectsToolWindow); MenuCommand menuToolWin = new MenuCommand(ShowToolWindow, toolwndCommandID); mcs.AddCommand(menuToolWin); } // Initialise the server list foreach (var server in this.configuration.Servers) { this.servers.AddServer(server); } // Attach the server list ToolWindowPane window = this.FindToolWindow(typeof(ProjectsToolWindow), 0, true); if ((null == window) || (null == window.Frame)) { throw new NotSupportedException(ToolWindowResources.CanNotCreateWindow); } var control = window.Window as ProjectsControl; control.AttachServerList(this.servers); } #endregion #endregion #region Private methods #region ShowToolWindow() /// /// This function is called when the user clicks the menu item that shows the /// tool window. See the Initialize method to see how the menu item is associated to /// this function using the OleMenuCommandService service and the MenuCommand class. /// private void ShowToolWindow(object sender, EventArgs e) { // Get the instance number 0 of this tool window. This window is single instance so this instance // is actually the only one. // The last flag is set to true so that if the tool window does not exists it will be created. ToolWindowPane window = this.FindToolWindow(typeof(ProjectsToolWindow), 0, true); if ((null == window) || (null == window.Frame)) { throw new NotSupportedException(ToolWindowResources.CanNotCreateWindow); } IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame; Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show()); } #endregion #region MenuItemCallback() /// /// This function is the callback used to execute a command when the a menu item is clicked. /// See the Initialize method to see how the menu item is associated to this function using /// the OleMenuCommandService service and the MenuCommand class. /// private void MenuItemCallback(object sender, EventArgs args) { var form = new SettingsForm(this); form.OkClicked += (o, e) => { UpdateServers(form.Configuration.Servers); this.configuration.Save(); }; form.ShowDialog(); } #endregion #region UpdateServers() /// /// Update all the servers. /// private void UpdateServers(IEnumerable servers) { var oldServers = (from record in this.configuration.Servers select record).ToList(); foreach (var server in servers) { // Check if the server already exists var oldServer = (from record in oldServers where (record.Address == server.Address) && (record.TargetServer == server.TargetServer) select record).SingleOrDefault(); if (oldServer == null) { // Add the server this.servers.AddServer(server); this.configuration.Servers.Add(server); } else { // Update the server this.servers.UpdateServer(server); server.Server = oldServer.Server; server.Server.DisplayName = server.Name; server.Server.Data.Set(server); // Don't remove the server oldServers.Remove(oldServer); } } // Remove any removed servers foreach (var oldServer in oldServers) { this.servers.RemoveServer(oldServer); this.configuration.Servers.Remove(oldServer); } } #endregion #endregion } }