-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
Selection.cs
151 lines (130 loc) · 5.46 KB
/
Selection.cs
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Threading;
using Task = System.Threading.Tasks.Task;
namespace Community.VisualStudio.Toolkit
{
/// <summary>
/// Services related to the selection of windows and items in solution.
/// </summary>
public class Selection
{
internal Selection()
{ }
/// <summary>
/// Gets the currently selected items.
/// </summary>
public async Task<IEnumerable<SolutionItem>> GetSelectedItemsAsync()
{
IEnumerable<IVsHierarchyItem>? hierarchies = await GetSelectedHierarchiesAsync();
List<SolutionItem> items = new();
foreach (IVsHierarchyItem hierarchy in hierarchies)
{
SolutionItem? item = await SolutionItem.FromHierarchyAsync(hierarchy.HierarchyIdentity.Hierarchy, hierarchy.HierarchyIdentity.ItemID);
if (item != null)
{
items.Add(item);
}
}
return items;
}
/// <summary>
/// Gets the currently selected item. If more than one item is selected, it returns the first one.
/// </summary>
/// <remarks><see langword="null"/> if no items are selected.</remarks>
public async Task<SolutionItem?> GetSelectedItemAsync()
{
IEnumerable<SolutionItem>? items = await GetSelectedItemsAsync();
return items?.FirstOrDefault();
}
/// <summary>
/// Sets the current UI context.
/// </summary>
/// <param name="uiContextGuid">The guid to uniquely identify the UI context.</param>
/// <param name="isActive">Determines if the UI context is active or not.</param>
public Task SetUIContextAsync(string uiContextGuid, bool isActive)
=> SetUIContextAsync(new Guid(uiContextGuid), isActive);
/// <summary>
/// Sets the current UI context.
/// </summary>
/// <param name="uiContextGuid">The guid to uniquely identify the UI context.</param>
/// <param name="isActive">Determines if the UI context is active or not.</param>
public async Task SetUIContextAsync(Guid uiContextGuid, bool isActive)
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
IVsMonitorSelection? svc = await VS.Services.GetMonitorSelectionAsync();
int cookieResult = svc.GetCmdUIContextCookie(uiContextGuid, out uint cookie);
ErrorHandler.ThrowOnFailure(cookieResult);
int setContextResult = svc.SetCmdUIContext(cookie, isActive ? 1 : 0);
ErrorHandler.ThrowOnFailure(setContextResult);
}
/// <summary>
/// Gets the currently selected hierarchy items.
/// </summary>
internal async Task<IEnumerable<IVsHierarchyItem>> GetSelectedHierarchiesAsync()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
IVsMonitorSelection? svc = await VS.Services.GetMonitorSelectionAsync();
IntPtr hierPtr = IntPtr.Zero;
IntPtr containerPtr = IntPtr.Zero;
List<IVsHierarchyItem> results = new();
try
{
svc.GetCurrentSelection(out hierPtr, out uint itemId, out IVsMultiItemSelect multiSelect, out containerPtr);
if (itemId == VSConstants.VSITEMID_SELECTION)
{
multiSelect.GetSelectionInfo(out uint itemCount, out int fSingleHierarchy);
VSITEMSELECTION[] items = new VSITEMSELECTION[itemCount];
multiSelect.GetSelectedItems(0, itemCount, items);
foreach (VSITEMSELECTION item in items)
{
IVsHierarchyItem? hierItem = await item.pHier.ToHierarcyItemAsync(item.itemid);
if (hierItem != null && !results.Contains(hierItem))
{
results.Add(hierItem);
}
}
}
else if (hierPtr != IntPtr.Zero)
{
IVsHierarchy hierarchy = (IVsHierarchy)Marshal.GetUniqueObjectForIUnknown(hierPtr);
IVsHierarchyItem? hierItem = await hierarchy.ToHierarcyItemAsync(itemId);
if (hierItem != null)
{
results.Add(hierItem);
}
}
else if (await VS.Services.GetSolutionAsync() is IVsHierarchy solution)
{
IVsHierarchyItem? sol = await solution.ToHierarcyItemAsync(VSConstants.VSITEMID_ROOT);
if (sol != null)
{
results.Add(sol);
}
}
}
catch (Exception ex)
{
await ex.LogAsync();
}
finally
{
if (hierPtr != IntPtr.Zero)
{
Marshal.Release(hierPtr);
}
if (containerPtr != IntPtr.Zero)
{
Marshal.Release(containerPtr);
}
}
return results;
}
}
}