-
Notifications
You must be signed in to change notification settings - Fork 363
Expand file tree
/
Copy pathFindInSolutionExplorerCommand.cs
More file actions
146 lines (128 loc) · 5.95 KB
/
FindInSolutionExplorerCommand.cs
File metadata and controls
146 lines (128 loc) · 5.95 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
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using SteveCadwallader.CodeMaid.Helpers;
using SteveCadwallader.CodeMaid.Properties;
using System;
using Task = System.Threading.Tasks.Task;
namespace SteveCadwallader.CodeMaid.Integration.Commands
{
/// <summary>
/// A command that provides for finding a file in the solution explorer.
/// </summary>
internal sealed class FindInSolutionExplorerCommand : BaseCommand
{
private readonly CommandHelper _commandHelper;
/// <summary>
/// Initializes a new instance of the <see cref="FindInSolutionExplorerCommand" /> class.
/// </summary>
/// <param name="package">The hosting package.</param>
internal FindInSolutionExplorerCommand(CodeMaidPackage package)
: base(package, PackageGuids.GuidCodeMaidMenuSet, PackageIds.CmdIDCodeMaidFindInSolutionExplorer)
{
_commandHelper = CommandHelper.GetInstance(package);
}
/// <summary>
/// A singleton instance of this command.
/// </summary>
public static FindInSolutionExplorerCommand Instance { get; private set; }
/// <summary>
/// Initializes a singleton instance of this command.
/// </summary>
/// <param name="package">The hosting package.</param>
/// <returns>A task.</returns>
public static Task InitializeAsync(CodeMaidPackage package)
{
Instance = new FindInSolutionExplorerCommand(package);
return package.SettingsMonitor.WatchAsync(s => s.Feature_FindInSolutionExplorer, Instance.SwitchAsync);
}
/// <summary>
/// Called to update the current status of the command.
/// </summary>
protected override void OnBeforeQueryStatus()
{
Enabled = Package.ActiveDocument != null;
}
/// <summary>
/// Called to execute the command.
/// </summary>
protected override void OnExecute()
{
base.OnExecute();
Document document = Package.ActiveDocument;
if (document != null)
{
if (Settings.Default.Finding_ClearSolutionExplorerSearch)
{
ClearSolutionExplorerSearchFilter();
}
if (Settings.Default.Finding_TemporarilyOpenSolutionFolders)
{
ToggleSolutionFoldersOpenTemporarily(UIHierarchyHelper.GetTopUIHierarchyItem(Package));
}
// Instead of directly using "SolutionExplorer.SyncWithActiveDocument" we are using
// the GUID/ID pair. This is a workaround for the canonical name being undefined in
// Spanish versions of Visual Studio.
var command = _commandHelper.FindCommand("{D63DB1F0-404E-4B21-9648-CA8D99245EC3}", 36);
if (command != null && command.IsAvailable)
{
object customIn = null;
object customOut = null;
Package.IDE.Commands.Raise(command.Guid, command.ID, ref customIn, ref customOut);
}
else
{
// The command will be unavailable if track active item is selected, and in those
// scenarios we just want to activate the solution explorer since the right item
// will already be highlighted.
Package.IDE.ExecuteCommand("View.SolutionExplorer", string.Empty);
}
}
}
/// <summary>
/// Clears any exising search filtering in the solution explorer so that items not matching
/// the query can be found.
/// </summary>
private void ClearSolutionExplorerSearchFilter()
{
var solutionExplorer = VsShellUtilities.GetUIHierarchyWindow(Package, VSConstants.StandardToolWindows.SolutionExplorer);
var ws = solutionExplorer as IVsWindowSearch;
ws?.ClearSearch();
}
/// <summary>
/// Toggles all solution folders open temporarily to workaround searches not working inside
/// solution folders that have never been expanded.
/// </summary>
/// <param name="parentItem">The parent item to inspect.</param>
private void ToggleSolutionFoldersOpenTemporarily(UIHierarchyItem parentItem)
{
if (parentItem == null)
{
throw new ArgumentNullException(nameof(parentItem));
}
const string solutionFolderGuid = "{66A26720-8FB5-11D2-AA7E-00C04F688DDE}";
var project = parentItem.Object as Project;
bool isCollapsedSolutionFolder = project != null && project.Kind == solutionFolderGuid && !parentItem.UIHierarchyItems.Expanded;
// Expand the solution folder temporarily.
if (isCollapsedSolutionFolder)
{
OutputWindowHelper.DiagnosticWriteLine($"FindInSolutionExplorerCommand.ToggleSolutionFoldersOpenTemporarily expanding '{parentItem.Name}'");
parentItem.Select(vsUISelectionType.vsUISelectionTypeSelect);
Package.IDE.ToolWindows.SolutionExplorer.DoDefaultAction();
}
// Run recursively to children as well for nested solution folders.
foreach (UIHierarchyItem childItem in parentItem.UIHierarchyItems)
{
ToggleSolutionFoldersOpenTemporarily(childItem);
}
// Collapse the solution folder.
if (isCollapsedSolutionFolder)
{
OutputWindowHelper.DiagnosticWriteLine($"FindInSolutionExplorerCommand.ToggleSolutionFoldersOpenTemporarily collapsing '{parentItem.Name}'");
parentItem.Select(vsUISelectionType.vsUISelectionTypeSelect);
Package.IDE.ToolWindows.SolutionExplorer.DoDefaultAction();
}
}
}
}