forked from parnic/VSQuickOpenFile
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenFileInSolutionPackage.cs
More file actions
213 lines (191 loc) · 7.88 KB
/
OpenFileInSolutionPackage.cs
File metadata and controls
213 lines (191 loc) · 7.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Interop;
using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
namespace PerniciousGames.OpenFileInSolution
{
public class ProjectItemWrapper
{
public string Filename { get; set; }
public ProjectItem ProjItem;
private ProjectItemWrapper()
{
}
public ProjectItemWrapper(ProjectItem inItem)
{
ProjItem = inItem;
Filename = inItem.FileNames[1];
}
}
/// <summary>
/// This is the class that implements the package exposed by this assembly.
///
/// The minimum requirement for a class to be considered a valid package for Visual Studio
/// is to implement the IVsPackage interface and register itself with the shell.
/// This package uses the helper classes defined inside the Managed Package Framework (MPF)
/// to do it: it derives from the Package class that provides the implementation of the
/// IVsPackage interface and uses the registration attributes defined in the framework to
/// register itself and its components with the shell.
/// </summary>
// This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
// a package.
[PackageRegistration(UseManagedResourcesOnly = true)]
// This attribute is used to register the information needed to show this package
// in the Help/About dialog of Visual Studio.
[InstalledProductRegistration(true, "#110", "#112", "1.5", IconResourceID = 400)]
[Guid(GuidList.guidOpenFileInSolutionPkgString)]
[ProvideMenuResource("Menus.ctmenu", 1)]
public sealed class OpenFileInSolutionPackage : Package
{
static readonly Guid ProjectFileGuid = new Guid("6BB5F8EE-4483-11D3-8BCF-00C04F8EC28C");
static readonly Guid ProjectFolderGuid = new Guid("6BB5F8EF-4483-11D3-8BCF-00C04F8EC28C");
static readonly Guid ProjectVirtualFolderGuid = new Guid("6BB5F8F0-4483-11D3-8BCF-00C04F8EC28C");
static readonly List<string> FileEndingsToSkip = new List<string>()
{
".vcxproj.filters",
".vcxproj"
};
/// <summary>
/// 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.
/// </summary>
public OpenFileInSolutionPackage()
{
Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
/////////////////////////////////////////////////////////////////////////////
// Overridden Package Implementation
#region Package Members
/// <summary>
/// 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 initialization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
base.Initialize();
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if (null != mcs)
{
// Create the command for the menu item.
CommandID menuCommandID = new CommandID(GuidList.guidOpenFileInSolutionCmdSet, 0x100);
MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
mcs.AddCommand(menuItem);
}
// todo: add option to jump between h and cpp?
}
#endregion
public static DTE2 GetActiveIDE()
{
// Get an instance of currently running Visual Studio IDE.
DTE2 dte2 = Package.GetGlobalService(typeof(DTE)) as DTE2;
return dte2;
}
public static IList<Project> GetProjects()
{
Projects projects = GetActiveIDE().Solution.Projects;
List<Project> list = new List<Project>();
var item = projects.GetEnumerator();
while (item.MoveNext())
{
var project = item.Current as Project;
if (project == null)
{
continue;
}
if (project.Kind == ProjectKinds.vsProjectKindSolutionFolder)
{
list.AddRange(GetSolutionFolderProjects(project));
}
else
{
list.Add(project);
}
}
return list;
}
private static IEnumerable<Project> GetSolutionFolderProjects(Project solutionFolder)
{
List<Project> list = new List<Project>();
for (var i = 1; i <= solutionFolder.ProjectItems.Count; i++)
{
var subProject = solutionFolder.ProjectItems.Item(i).SubProject;
if (subProject == null)
{
continue;
}
// If this is another solution folder, do a recursive call, otherwise add
if (subProject.Kind == ProjectKinds.vsProjectKindSolutionFolder)
{
list.AddRange(GetSolutionFolderProjects(subProject));
}
else
{
list.Add(subProject);
}
}
return list;
}
private IEnumerable<ProjectItemWrapper> EnumerateProjectItems(ProjectItems items)
{
if (items != null)
{
for (int i = 1; i <= items.Count; i++)
{
var itm = items.Item(i);
var itmGuid = Guid.Parse(itm.Kind);
if (itmGuid.Equals(ProjectFolderGuid))
{
continue;
}
foreach (var res in EnumerateProjectItems(itm.ProjectItems))
{
yield return res;
}
if (itmGuid.Equals(ProjectVirtualFolderGuid))
{
continue;
}
for (short j = 0; itm != null && j < itm.FileCount; j++)
{
bool bSkip = false;
foreach (var ending in FileEndingsToSkip)
{
if (itm.FileNames[1].EndsWith(ending))
{
bSkip = true;
break;
}
}
if (!bSkip)
{
yield return new ProjectItemWrapper(itm);
}
}
}
}
}
private void MenuItemCallback(object sender, EventArgs e)
{
var projItems = new List<ProjectItemWrapper>();
foreach (var proj in GetProjects())
{
projItems.AddRange(EnumerateProjectItems(proj.ProjectItems));
}
var wnd = new ListFiles(projItems);
wnd.Owner = HwndSource.FromHwnd(new IntPtr(GetActiveIDE().MainWindow.HWnd)).RootVisual as System.Windows.Window;
wnd.Width = wnd.Owner.Width / 2;
wnd.Height = wnd.Owner.Height / 3;
wnd.ShowDialog();
}
}
}