OLD | NEW |
| (Empty) |
1 /// Copyright (c) Microsoft Corporation. All rights reserved. | |
2 | |
3 using System; | |
4 using System.Diagnostics; | |
5 using System.Globalization; | |
6 using System.Runtime.InteropServices; | |
7 using Microsoft.VisualStudio; | |
8 using Microsoft.VisualStudio.Shell; | |
9 using Microsoft.VisualStudio.Shell.Interop; | |
10 using IServiceProvider = System.IServiceProvider; | |
11 using ShellConstants = Microsoft.VisualStudio.Shell.Interop.Constants; | |
12 | |
13 namespace Microsoft.VisualStudio.Project | |
14 { | |
15 /// <summary> | |
16 /// This abstract class handles opening, saving of items in the hierarch
y. | |
17 /// </summary> | |
18 [CLSCompliant(false)] | |
19 public abstract class DocumentManager | |
20 { | |
21 #region fields | |
22 private HierarchyNode node = null; | |
23 #endregion | |
24 | |
25 #region properties | |
26 protected HierarchyNode Node | |
27 { | |
28 get | |
29 { | |
30 return this.node; | |
31 } | |
32 } | |
33 #endregion | |
34 | |
35 #region ctors | |
36 protected DocumentManager(HierarchyNode node) | |
37 { | |
38 this.node = node; | |
39 } | |
40 #endregion | |
41 | |
42 #region virtual methods | |
43 | |
44 /// <summary> | |
45 /// Open a document using the standard editor. This method has n
o implementation since a document is abstract in this context | |
46 /// </summary> | |
47 /// <param name="logicalView">In MultiView case determines view
to be activated by IVsMultiViewDocumentView. For a list of logical view GUIDS, s
ee constants starting with LOGVIEWID_ defined in NativeMethods class</param> | |
48 /// <param name="docDataExisting">IntPtr to the IUnknown interfa
ce of the existing document data object</param> | |
49 /// <param name="windowFrame">A reference to the window frame th
at is mapped to the document</param> | |
50 /// <param name="windowFrameAction">Determine the UI action on t
he document window</param> | |
51 /// <returns>NotImplementedException</returns> | |
52 /// <remarks>See FileDocumentManager class for an implementation
of this method</remarks> | |
53 public virtual int Open(ref Guid logicalView, IntPtr docDataExis
ting, out IVsWindowFrame windowFrame, WindowFrameShowAction windowFrameAction) | |
54 { | |
55 throw new NotImplementedException(); | |
56 } | |
57 | |
58 /// <summary> | |
59 /// Open a document using a specific editor. This method has no
implementation. | |
60 /// </summary> | |
61 /// <param name="editorFlags">Specifies actions to take when ope
ning a specific editor. Possible editor flags are defined in the enumeration Mic
rosoft.VisualStudio.Shell.Interop.__VSOSPEFLAGS</param> | |
62 /// <param name="editorType">Unique identifier of the editor typ
e</param> | |
63 /// <param name="physicalView">Name of the physical view. If nul
l, the environment calls MapLogicalView on the editor factory to determine the p
hysical view that corresponds to the logical view. In this case, null does not s
pecify the primary view, but rather indicates that you do not know which view co
rresponds to the logical view</param> | |
64 /// <param name="logicalView">In MultiView case determines view
to be activated by IVsMultiViewDocumentView. For a list of logical view GUIDS, s
ee constants starting with LOGVIEWID_ defined in NativeMethods class</param> | |
65 /// <param name="docDataExisting">IntPtr to the IUnknown interfa
ce of the existing document data object</param> | |
66 /// <param name="frame">A reference to the window frame that is
mapped to the document</param> | |
67 /// <param name="windowFrameAction">Determine the UI action on t
he document window</param> | |
68 /// <returns>NotImplementedException</returns> | |
69 /// <remarks>See FileDocumentManager for an implementation of th
is method</remarks> | |
70 public virtual int OpenWithSpecific(uint editorFlags, ref Guid e
ditorType, string physicalView, ref Guid logicalView, IntPtr docDataExisting, ou
t IVsWindowFrame frame, WindowFrameShowAction windowFrameAction) | |
71 { | |
72 throw new NotImplementedException(); | |
73 } | |
74 | |
75 /// <summary> | |
76 /// Close an open document window | |
77 /// </summary> | |
78 /// <param name="closeFlag">Decides how to close the document</p
aram> | |
79 /// <returns>S_OK if successful, otherwise an error is returned<
/returns> | |
80 public virtual int Close(__FRAMECLOSE closeFlag) | |
81 { | |
82 if(this.node == null || this.node.ProjectMgr == null ||
this.node.ProjectMgr.IsClosed) | |
83 { | |
84 return VSConstants.E_FAIL; | |
85 } | |
86 | |
87 // Get info about the document | |
88 bool isDirty, isOpen, isOpenedByUs; | |
89 uint docCookie; | |
90 IVsPersistDocData ppIVsPersistDocData; | |
91 this.GetDocInfo(out isOpen, out isDirty, out isOpenedByU
s, out docCookie, out ppIVsPersistDocData); | |
92 | |
93 if(isOpenedByUs) | |
94 { | |
95 IVsUIShellOpenDocument shell = this.Node.Project
Mgr.Site.GetService(typeof(IVsUIShellOpenDocument)) as IVsUIShellOpenDocument; | |
96 Guid logicalView = Guid.Empty; | |
97 uint grfIDO = 0; | |
98 IVsUIHierarchy pHierOpen; | |
99 uint[] itemIdOpen = new uint[1]; | |
100 IVsWindowFrame windowFrame; | |
101 int fOpen; | |
102 ErrorHandler.ThrowOnFailure(shell.IsDocumentOpen
(this.Node.ProjectMgr, this.Node.ID, this.Node.Url, ref logicalView, grfIDO, out
pHierOpen, itemIdOpen, out windowFrame, out fOpen)); | |
103 | |
104 if(windowFrame != null) | |
105 { | |
106 docCookie = 0; | |
107 return windowFrame.CloseFrame((uint)clos
eFlag); | |
108 } | |
109 } | |
110 | |
111 return VSConstants.S_OK; | |
112 } | |
113 | |
114 /// <summary> | |
115 /// Silently saves an open document | |
116 /// </summary> | |
117 /// <param name="saveIfDirty">Save the open document only if it
is dirty</param> | |
118 /// <remarks>The call to SaveDocData may return Microsoft.Visual
Studio.Shell.Interop.PFF_RESULTS.STG_S_DATALOSS to indicate some characters coul
d not be represented in the current codepage</remarks> | |
119 public virtual void Save(bool saveIfDirty) | |
120 { | |
121 bool isDirty, isOpen, isOpenedByUs; | |
122 uint docCookie; | |
123 IVsPersistDocData persistDocData; | |
124 this.GetDocInfo(out isOpen, out isDirty, out isOpenedByU
s, out docCookie, out persistDocData); | |
125 if(isDirty && saveIfDirty && persistDocData != null) | |
126 { | |
127 string name; | |
128 int cancelled; | |
129 ErrorHandler.ThrowOnFailure(persistDocData.SaveD
ocData(VSSAVEFLAGS.VSSAVE_SilentSave, out name, out cancelled)); | |
130 } | |
131 } | |
132 | |
133 #endregion | |
134 | |
135 #region helper methods | |
136 /// <summary> | |
137 /// Get document properties from RDT | |
138 /// </summary> | |
139 internal void GetDocInfo( | |
140 out bool isOpen, // true if the doc is opened | |
141 out bool isDirty, // true if the doc is dirty | |
142 out bool isOpenedByUs, // true if opened by our project | |
143 out uint docCookie, // VSDOCCOOKIE if open | |
144 out IVsPersistDocData persistDocData) | |
145 { | |
146 isOpen = isDirty = isOpenedByUs = false; | |
147 docCookie = (uint)ShellConstants.VSDOCCOOKIE_NIL; | |
148 persistDocData = null; | |
149 | |
150 if(this.node == null || this.node.ProjectMgr == null ||
this.node.ProjectMgr.IsClosed) | |
151 { | |
152 return; | |
153 } | |
154 | |
155 IVsHierarchy hierarchy; | |
156 uint vsitemid = VSConstants.VSITEMID_NIL; | |
157 | |
158 VsShellUtilities.GetRDTDocumentInfo(this.node.ProjectMgr
.Site, this.node.Url, out hierarchy, out vsitemid, out persistDocData, out docCo
okie); | |
159 | |
160 if(hierarchy == null || docCookie == (uint)ShellConstant
s.VSDOCCOOKIE_NIL) | |
161 { | |
162 return; | |
163 } | |
164 | |
165 isOpen = true; | |
166 // check if the doc is opened by another project | |
167 if(Utilities.IsSameComObject(this.node.ProjectMgr, hiera
rchy)) | |
168 { | |
169 isOpenedByUs = true; | |
170 } | |
171 | |
172 if(persistDocData != null) | |
173 { | |
174 int isDocDataDirty; | |
175 ErrorHandler.ThrowOnFailure(persistDocData.IsDoc
DataDirty(out isDocDataDirty)); | |
176 isDirty = (isDocDataDirty != 0); | |
177 } | |
178 } | |
179 | |
180 protected string GetOwnerCaption() | |
181 { | |
182 Debug.Assert(this.node != null, "No node has been initia
lized for the document manager"); | |
183 | |
184 object pvar; | |
185 ErrorHandler.ThrowOnFailure(this.node.GetProperty(this.n
ode.ID, (int)__VSHPROPID.VSHPROPID_Caption, out pvar)); | |
186 | |
187 return (pvar as string); | |
188 } | |
189 | |
190 protected static void CloseWindowFrame(ref IVsWindowFrame window
Frame) | |
191 { | |
192 if(windowFrame != null) | |
193 { | |
194 try | |
195 { | |
196 ErrorHandler.ThrowOnFailure(windowFrame.
CloseFrame(0)); | |
197 } | |
198 finally | |
199 { | |
200 windowFrame = null; | |
201 } | |
202 } | |
203 } | |
204 | |
205 protected string GetFullPathForDocument() | |
206 { | |
207 string fullPath = String.Empty; | |
208 | |
209 Debug.Assert(this.node != null, "No node has been initia
lized for the document manager"); | |
210 | |
211 // Get the URL representing the item | |
212 fullPath = this.node.GetMkDocument(); | |
213 | |
214 Debug.Assert(!String.IsNullOrEmpty(fullPath), "Could not
retrive the fullpath for the node" + this.Node.ID.ToString(CultureInfo.CurrentC
ulture)); | |
215 return fullPath; | |
216 } | |
217 | |
218 #endregion | |
219 | |
220 #region static methods | |
221 /// <summary> | |
222 /// Updates the caption for all windows associated to the docume
nt. | |
223 /// </summary> | |
224 /// <param name="site">The service provider.</param> | |
225 /// <param name="caption">The new caption.</param> | |
226 /// <param name="docData">The IUnknown interface to a document d
ata object associated with a registered document.</param> | |
227 public static void UpdateCaption(IServiceProvider site, string c
aption, IntPtr docData) | |
228 { | |
229 if(site == null) | |
230 { | |
231 throw new ArgumentNullException("site"); | |
232 } | |
233 | |
234 if(String.IsNullOrEmpty(caption)) | |
235 { | |
236 throw new ArgumentException(SR.GetString(SR.Para
meterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "caption"); | |
237 } | |
238 | |
239 IVsUIShell uiShell = site.GetService(typeof(SVsUIShell))
as IVsUIShell; | |
240 | |
241 // We need to tell the windows to update their captions.
| |
242 IEnumWindowFrames windowFramesEnum; | |
243 ErrorHandler.ThrowOnFailure(uiShell.GetDocumentWindowEnu
m(out windowFramesEnum)); | |
244 IVsWindowFrame[] windowFrames = new IVsWindowFrame[1]; | |
245 uint fetched; | |
246 while(windowFramesEnum.Next(1, windowFrames, out fetched
) == VSConstants.S_OK && fetched == 1) | |
247 { | |
248 IVsWindowFrame windowFrame = windowFrames[0]; | |
249 object data; | |
250 ErrorHandler.ThrowOnFailure(windowFrame.GetPrope
rty((int)__VSFPROPID.VSFPROPID_DocData, out data)); | |
251 IntPtr ptr = Marshal.GetIUnknownForObject(data); | |
252 try | |
253 { | |
254 if(ptr == docData) | |
255 { | |
256 ErrorHandler.ThrowOnFailure(wind
owFrame.SetProperty((int)__VSFPROPID.VSFPROPID_OwnerCaption, caption)); | |
257 } | |
258 } | |
259 finally | |
260 { | |
261 if(ptr != IntPtr.Zero) | |
262 { | |
263 Marshal.Release(ptr); | |
264 } | |
265 } | |
266 } | |
267 } | |
268 | |
269 /// <summary> | |
270 /// Rename document in the running document table from oldName t
o newName. | |
271 /// </summary> | |
272 /// <param name="provider">The service provider.</param> | |
273 /// <param name="oldName">Full path to the old name of the docum
ent.</param> | |
274 /// <param name="newName">Full path to the new name of the docum
ent.</param> | |
275 /// <param name="newItemId">The new item id of the document</par
am> | |
276 public static void RenameDocument(IServiceProvider site, string
oldName, string newName, uint newItemId) | |
277 { | |
278 if(site == null) | |
279 { | |
280 throw new ArgumentNullException("site"); | |
281 } | |
282 | |
283 if(String.IsNullOrEmpty(oldName)) | |
284 { | |
285 throw new ArgumentException(SR.GetString(SR.Para
meterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "oldName"); | |
286 } | |
287 | |
288 if(String.IsNullOrEmpty(newName)) | |
289 { | |
290 throw new ArgumentException(SR.GetString(SR.Para
meterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "newName"); | |
291 } | |
292 | |
293 if(newItemId == VSConstants.VSITEMID_NIL) | |
294 { | |
295 throw new ArgumentNullException("newItemId"); | |
296 } | |
297 | |
298 IVsRunningDocumentTable pRDT = site.GetService(typeof(SV
sRunningDocumentTable)) as IVsRunningDocumentTable; | |
299 IVsUIShellOpenDocument doc = site.GetService(typeof(SVsU
IShellOpenDocument)) as IVsUIShellOpenDocument; | |
300 | |
301 if(pRDT == null || doc == null) return; | |
302 | |
303 IVsHierarchy pIVsHierarchy; | |
304 uint itemId; | |
305 IntPtr docData; | |
306 uint uiVsDocCookie; | |
307 ErrorHandler.ThrowOnFailure(pRDT.FindAndLockDocument((ui
nt)_VSRDTFLAGS.RDT_NoLock, oldName, out pIVsHierarchy, out itemId, out docData,
out uiVsDocCookie)); | |
308 | |
309 if(docData != IntPtr.Zero) | |
310 { | |
311 try | |
312 { | |
313 IntPtr pUnk = Marshal.GetIUnknownForObje
ct(pIVsHierarchy); | |
314 Guid iid = typeof(IVsHierarchy).GUID; | |
315 IntPtr pHier; | |
316 Marshal.QueryInterface(pUnk, ref iid, ou
t pHier); | |
317 try | |
318 { | |
319 ErrorHandler.ThrowOnFailure(pRDT
.RenameDocument(oldName, newName, pHier, newItemId)); | |
320 } | |
321 finally | |
322 { | |
323 if(pHier != IntPtr.Zero) | |
324 Marshal.Release(pHier); | |
325 if(pUnk != IntPtr.Zero) | |
326 Marshal.Release(pUnk); | |
327 } | |
328 } | |
329 finally | |
330 { | |
331 Marshal.Release(docData); | |
332 } | |
333 } | |
334 } | |
335 #endregion | |
336 } | |
337 } | |
OLD | NEW |