namespace SolutionOpen
{
using System;
using Microsoft.VisualStudio.CommandBars;
using Extensibility;
using EnvDTE;
using EnvDTE80;
using System.Windows.Forms;
using System.Collections.Specialized;
/// The object for implementing an Add-in.
///
public class Connect : Object, IDTExtensibility2, IDTCommandTarget
{
/// Implements the constructor for the Add-in object. Place your initialization code within this method.
public Connect()
{
}
/// Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.
/// Root object of the host application.
/// Describes how the Add-in is being loaded.
/// Object representing this Add-in.
///
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
applicationObject = (DTE2)application;
addInInstance = (AddIn)addInInst;
if (connectMode == ext_ConnectMode.ext_cm_UISetup)
{
object[] contextGUIDS = new object[] { };
Commands2 commands = (Commands2)applicationObject.Commands;
try
{
//Add a command to the Commands collection:
Command command = commands.AddNamedCommand2(addInInstance, "SolutionOpen", "SolutionOpen", "Open files from anywhere within the solution", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
Command command2 = commands.AddNamedCommand2(addInInstance, "HeaderFlip", "HeaderFlip", "Flips through all the files with the same base name", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
Command command3 = commands.AddNamedCommand2(addInInstance, "RefreshFileList", "RefreshFileList", "Refreshes the list of files in the solution from the project files", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton);
}
catch (Exception)
{
}
}
}
/// Implements the OnDisconnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being unloaded.
/// Describes how the Add-in is being unloaded.
/// Array of parameters that are host application specific.
///
public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom)
{
}
/// Implements the OnAddInsUpdate method of the IDTExtensibility2 interface. Receives notification when the collection of Add-ins has changed.
/// Array of parameters that are host application specific.
///
public void OnAddInsUpdate(ref Array custom)
{
}
/// Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.
/// Array of parameters that are host application specific.
///
public void OnStartupComplete(ref Array custom)
{
}
/// Implements the OnBeginShutdown method of the IDTExtensibility2 interface. Receives notification that the host application is being unloaded.
/// Array of parameters that are host application specific.
///
public void OnBeginShutdown(ref Array custom)
{
}
/// Implements the QueryStatus method of the IDTCommandTarget interface. This is called when the command's availability is updated
/// The name of the command to determine state for.
/// Text that is needed for the command.
/// The state of the command in the user interface.
/// Text requested by the neededText parameter.
///
public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText)
{
if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)
{
if (commandName == "SolutionOpen.Connect.SolutionOpen" || commandName == "SolutionOpen.Connect.HeaderFlip" || commandName == "SolutionOpen.Connect.RefreshFileList")
{
status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled;
}
}
}
private String BaseName(string fullName)
{
int fileNameStart = fullName.LastIndexOfAny("\\/".ToCharArray()) + 1;
int firstDot = fullName.IndexOf('.', fileNameStart);
if (firstDot > 0)
return fullName.Substring(fileNameStart, (firstDot - fileNameStart));
return fullName;
}
/// Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.
/// The name of the command to execute.
/// Describes how the command should be run.
/// Parameters passed from the caller to the command handler.
/// Parameters passed from the command handler to the caller.
/// Informs the caller if the command was handled or not.
///
public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
{
handled = false;
if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
{
bool refreshFileList = false;
if (commandName == "SolutionOpen.Connect.RefreshFileList")
{
handled = true;
refreshFileList = true;
}
if (refreshFileList || filePaths.Count == 0)
{
// get the list of files in the project
filePaths.Clear();
EnvDTE.Projects projects = applicationObject.Solution.Projects;
for (int i = 1; i <= projects.Count; ++i)
FindFiles(projects.Item(i).ProjectItems, ref filePaths);
// return if all that was requested was a file list refresh
if (handled)
return;
}
if (commandName == "SolutionOpen.Connect.SolutionOpen")
{
// show the dialog box and handle what the user wants to do
ChooseFile chooseFile = new ChooseFile(ref applicationObject, ref filePaths);
if (chooseFile.ShowDialog() == DialogResult.OK)
chooseFile.OpenSelectedFiles();
// clean up
chooseFile.Dispose();
handled = true;
return;
}
else if (commandName == "SolutionOpen.Connect.HeaderFlip")
{
// make sure there is an active document
if (applicationObject.ActiveDocument != null)
{
// Get the current active document and its base name
String activeDocumentFullName = applicationObject.ActiveDocument.FullName;
String activeDocumentBaseName = BaseName(activeDocumentFullName);
// find the files with the same base name
StringCollection matchingFilePaths = new StringCollection();
foreach (String fullName in filePaths.Values)
{
String baseName = BaseName(fullName);
if (String.Compare(activeDocumentBaseName, baseName, true) == 0)
matchingFilePaths.Add(fullName);
}
// make sure that we have more than one of them open before we try to switch
if (matchingFilePaths.Count > 1)
{
// figure out which document in the list (if any) is the current document
int activeDocumentIndex = -1;
for (int i = 0; activeDocumentIndex < 0 && i < matchingFilePaths.Count; ++i)
{
if (String.Compare(activeDocumentFullName, matchingFilePaths[i], true) == 0)
activeDocumentIndex = i;
}
// make sure we found this document
if (activeDocumentIndex >= 0)
{
// figure out which document comes next
int nextDocument = activeDocumentIndex + 1;
if (nextDocument >= matchingFilePaths.Count)
nextDocument = 0;
// open and display that document
applicationObject.ItemOperations.OpenFile(matchingFilePaths[nextDocument], EnvDTE.Constants.vsViewKindAny);
}
}
handled = true;
return;
}
}
}
}
private void FindFiles(EnvDTE.ProjectItems projectItems, ref StringDictionary filePaths)
{
foreach (EnvDTE.ProjectItem projectItem in projectItems)
{
// check all the files in this project item
for (int i = 0; i < projectItem.FileCount; ++i)
{
// Make sure the project item is a physical file
if (projectItem.Kind == "{6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C}")
{
String fileName = projectItem.get_FileNames(1);
if (fileName != null)
filePaths[fileName] = fileName;
}
}
// recurse into any project items within this project item
if (projectItem.ProjectItems != null)
FindFiles(projectItem.ProjectItems, ref filePaths);
// handle sub-projects
if (projectItem.SubProject != null)
FindFiles(projectItem.SubProject.ProjectItems, ref filePaths);
}
}
private DTE2 applicationObject;
private AddIn addInInstance;
private StringDictionary filePaths = new StringDictionary();
}
}