added some development tools
[windows-sources.git] / developer / VSSDK / VisualStudioIntegration / Common / Source / CSharp / Shell / Flavor / Project.cs
blobccffaebc10d850d4368f37e03850382d6f44de1d
1 /***************************************************************************
2 Copyright (c) Microsoft Corporation, All rights reserved.
3 This code sample is provided "AS IS" without warranty of any kind,
4 it is not recommended for use in a production environment.
5 ***************************************************************************/
7 namespace Microsoft.VisualStudio.Shell.Flavor
9 using System;
10 using System.Diagnostics;
11 using System.Globalization;
12 using System.Runtime.InteropServices;
13 using Microsoft.VisualStudio.Shell.Interop;
14 using Microsoft.VisualStudio.OLE.Interop;
15 using Microsoft.VisualStudio.Shell;
17 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject"]/*' />
18 /// <devdoc>
19 /// A project that is a subtype/flavor of an inner project.
20 /// The default behavior of all methods is to delegate to the
21 /// inner project. For any behavior you want to change, simply
22 /// handle the request yourself.
23 /// </devdoc>
24 [CLSCompliant(false)]
25 public abstract class FlavoredProject :
26 Microsoft.VisualStudio.ProjectAggregator.CProjectAggregatorClass, // Provide aggregation support
27 IVsAggregatableProject,
28 System.IServiceProvider,
29 IVsHierarchy,
30 IVsUIHierarchy,
31 IOleCommandTarget,
32 IVsTrackProjectDocumentsEvents2
34 // Keep interface reference for all interface we override
36 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.innerVsAggregatableProject"]/*' />
37 protected IVsAggregatableProject innerVsAggregatableProject;
38 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.innerVsHierarchy"]/*' />
39 protected IVsHierarchy innerVsHierarchy;
40 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.innerVsUIHierarchy"]/*' />
41 protected IVsUIHierarchy innerVsUIHierarchy;
42 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.innerOleCommandTarget"]/*' />
43 protected IOleCommandTarget innerOleCommandTarget;
45 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.serviceProvider"]/*' />
46 protected System.IServiceProvider serviceProvider;
48 private OleMenuCommandService menuService;
50 uint cookie = 0;
52 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FlavoredProject"]/*' />
53 public FlavoredProject()
57 #region IVsAggregatableProject
59 /// <devdoc>
60 /// This is were all QI for interface on the inner object should happen
61 /// Then set the inner project
62 /// wait for InitializeForOuter to be called to do the real initialization
63 /// </devdoc>
64 int IVsAggregatableProject.SetInnerProject(object inner)
66 // delegate to the protected method
67 this.SetInnerProject(inner);
69 return NativeMethods.S_OK;
72 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SetInnerProject"]/*' />
73 /// <devdoc>
74 /// This is were all QI for interface on the inner object should happen
75 /// Then set the inner project
76 /// wait for InitializeForOuter to be called to do the real initialization
77 /// </devdoc>
78 protected virtual void SetInnerProject(object inner)
80 // Keep a reference to each interface we want to call on the inner project
81 // we must do it now as once we call SetInner the AddRef would be forwarded to ourselves
82 innerVsAggregatableProject = (IVsAggregatableProject)inner;
83 innerVsHierarchy = (IVsHierarchy)inner;
84 innerVsUIHierarchy = (IVsUIHierarchy)inner;
85 // As should return null without throwing in the event the base project does not implement the interface
86 innerOleCommandTarget = inner as IOleCommandTarget;
88 // Setup our menu command service
89 if (this.serviceProvider == null)
90 throw new NotSupportedException("serviceProvider should have been set before SetInnerProject gets called.");
91 menuService = new OleMenuCommandService(this, innerOleCommandTarget);
93 // Aggregate the project
94 this.SetInner(inner);
97 /// <devdoc>
98 /// Do the initialization here (such as loading flavor specific
99 /// information from the project)
100 /// </devdoc>
101 int IVsAggregatableProject.InitializeForOuter(string fileName, string location, string name,
102 uint flags, ref Guid guidProject, out IntPtr project, out int canceled)
104 if (innerVsAggregatableProject == null || guidProject != NativeMethods.IID_IUnknown)
105 throw new NotSupportedException();
107 Marshal.QueryInterface(Marshal.GetIUnknownForObject(this), ref guidProject, out project);
109 canceled = 0;
110 bool cancel;
111 this.InitializeForOuter(fileName, location, name, flags, ref guidProject, out cancel);
112 if (cancel)
113 canceled = 1;
115 return NativeMethods.S_OK;
118 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.InitializeForOuter"]/*' />
119 /// <devdoc>
120 /// Allow the project to initialize itself.
121 /// At this point it possible to call the inner project
122 /// Also allow canceling the project creation
123 /// </devdoc>
124 /// <returns>Return true to cancel the project creation</returns>
125 protected virtual void InitializeForOuter(string fileName, string location, string name, uint flags, ref Guid guidProject, out bool cancel)
127 cancel = false;
129 /// <devdoc>
130 /// This is called when all object in aggregation have received InitializeForOuter calls.
131 /// At this point the aggregation is complete and fully functional.
132 /// </devdoc>
133 int IVsAggregatableProject.OnAggregationComplete()
135 this.OnAggregationComplete();
136 if (innerVsAggregatableProject != null)
137 return innerVsAggregatableProject.OnAggregationComplete();
138 return NativeMethods.S_OK;
141 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.OnAggregationComplete"]/*' />
142 /// <devdoc>
143 /// This is called when all object in aggregation have received InitializeForOuter calls.
144 /// At this point the aggregation is complete and fully functional.
145 /// </devdoc>
146 protected virtual void OnAggregationComplete()
148 // This will subscribe to the IVsTrackProjectDocumentsEvents.
149 // This is not required to flavor a project but makes it easier for derived class
150 // to subscribe to these events.
151 IVsTrackProjectDocuments2 trackDocuments = GetTrackProjectDocuments();
152 ErrorHandler.ThrowOnFailure(trackDocuments.AdviseTrackProjectDocumentsEvents(this, out cookie));
155 /// <devdoc>
156 /// This must be delegetated to the inner most project
157 /// </devdoc>
158 int IVsAggregatableProject.SetAggregateProjectTypeGuids(string projectTypeGuids)
160 if (innerVsAggregatableProject == null)
161 throw new NotSupportedException();
163 return innerVsAggregatableProject.SetAggregateProjectTypeGuids(projectTypeGuids);
166 /// <devdoc>
167 /// This must be delegetated to the inner most project
168 /// </devdoc>
169 int IVsAggregatableProject.GetAggregateProjectTypeGuids(out string projectTypeGuids)
171 if (innerVsAggregatableProject == null)
172 throw new NotSupportedException();
174 return innerVsAggregatableProject.GetAggregateProjectTypeGuids(out projectTypeGuids);
177 #endregion
179 #region IVsHierarchy
181 // Most methods call protected virtual methods which delegate to the inner project.
182 // Derived classes should override those protected method if they want to change the
183 // behavior.
186 int IVsHierarchy.AdviseHierarchyEvents(Microsoft.VisualStudio.Shell.Interop.IVsHierarchyEvents eventSink, out uint cookie)
188 cookie = this.AdviseHierarchyEvents(eventSink);
189 return NativeMethods.S_OK;
192 int IVsHierarchy.Close()
194 if (cookie != 0)
196 // Unsubscribe to events
197 IVsTrackProjectDocuments2 trackDocuments = GetTrackProjectDocuments();
198 Debug.Assert(ErrorHandler.Succeeded(trackDocuments.UnadviseTrackProjectDocumentsEvents(cookie)), "Failed to UnadviseTrackProjectDocumentsEvents");
199 cookie = 0;
201 this.Close();
202 return NativeMethods.S_OK;
205 int IVsHierarchy.GetCanonicalName(uint itemId, out string name)
207 return this.GetCanonicalName(itemId, out name);
210 int IVsHierarchy.GetGuidProperty(uint itemId, int propId, out System.Guid guid)
212 guid = this.GetGuidProperty(itemId, propId);
213 return NativeMethods.S_OK;
216 int IVsHierarchy.GetNestedHierarchy(uint itemId, ref System.Guid guidHierarchyNested, out System.IntPtr hierarchyNested, out uint itemIdNested)
218 return this.GetNestedHierarchy(itemId, ref guidHierarchyNested, out hierarchyNested, out itemIdNested);
221 int IVsHierarchy.GetProperty(uint itemId, int propId, out System.Object property)
223 // While other methods expect the protected method to throw, for GetProperty
224 // we break this pattern as it is called much more often and it is legitimate to
225 // return not implemented. Therefore it can help perf and debugging experience
226 return this.GetProperty(itemId, propId, out property);
229 int IVsHierarchy.GetSite(out Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider)
231 serviceProvider = this.GetSite();
232 return NativeMethods.S_OK;
235 int IVsHierarchy.ParseCanonicalName(string name, out uint itemId)
237 return this.ParseCanonicalName(name, out itemId);
240 int IVsHierarchy.QueryClose(out int canClose)
242 canClose = 0;
243 if (this.QueryClose())
244 canClose = 1;
245 return NativeMethods.S_OK;
248 int IVsHierarchy.SetGuidProperty(uint itemId, int propId, ref System.Guid guid)
250 this.SetGuidProperty(itemId, propId, ref guid);
251 return NativeMethods.S_OK;
254 int IVsHierarchy.SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider)
256 this.serviceProvider = (System.IServiceProvider)new ServiceProvider(serviceProvider);
257 NativeMethods.ThrowOnFailure(innerVsHierarchy.SetSite(serviceProvider));
258 return NativeMethods.S_OK;
261 int IVsHierarchy.UnadviseHierarchyEvents(uint cookie)
263 this.UnadviseHierarchyEvents(cookie);
264 return NativeMethods.S_OK;
267 int IVsHierarchy.SetProperty(uint itemId, int propId, System.Object property)
269 return this.SetProperty(itemId, propId, property);
272 int IVsHierarchy.Unused0()
274 this.Unused0();
275 return NativeMethods.S_OK;
278 int IVsHierarchy.Unused1()
280 this.Unused1();
281 return NativeMethods.S_OK;
284 int IVsHierarchy.Unused2()
286 this.Unused2();
287 return NativeMethods.S_OK;
290 int IVsHierarchy.Unused3()
292 this.Unused3();
293 return NativeMethods.S_OK;
296 int IVsHierarchy.Unused4()
298 this.Unused4();
299 return NativeMethods.S_OK;
302 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.AdviseHierarchyEvents"]/*' />
303 protected virtual uint AdviseHierarchyEvents(Microsoft.VisualStudio.Shell.Interop.IVsHierarchyEvents eventSink)
305 uint cookie=0;
306 NativeMethods.ThrowOnFailure(innerVsHierarchy.AdviseHierarchyEvents(eventSink, out cookie));
307 return cookie;
310 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Close"]/*' />
311 protected virtual void Close()
313 NativeMethods.ThrowOnFailure(innerVsHierarchy.Close());
316 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.GetCanonicalName"]/*' />
317 protected virtual int GetCanonicalName(uint itemId, out string name)
319 return innerVsHierarchy.GetCanonicalName(itemId, out name);
322 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.GetGuidProperty"]/*' />
323 protected virtual Guid GetGuidProperty(uint itemId, int propId)
325 Guid property;
326 NativeMethods.ThrowOnFailure(innerVsHierarchy.GetGuidProperty(itemId, propId, out property));
327 return property;
330 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.GetNestedHierarchy"]/*' />
331 protected virtual int GetNestedHierarchy(uint itemId, ref System.Guid guidHierarchyNested, out System.IntPtr hierarchyNested, out uint itemIdNested)
333 return innerVsHierarchy.GetNestedHierarchy(itemId, ref guidHierarchyNested, out hierarchyNested, out itemIdNested);
336 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.GetProperty"]/*' />
337 protected virtual int GetProperty(uint itemId, int propId, out Object property)
339 return innerVsHierarchy.GetProperty(itemId, propId, out property);
342 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.GetSite"]/*' />
343 protected virtual Microsoft.VisualStudio.OLE.Interop.IServiceProvider GetSite()
345 Microsoft.VisualStudio.OLE.Interop.IServiceProvider serviceProvider;
346 NativeMethods.ThrowOnFailure(innerVsHierarchy.GetSite(out serviceProvider));
347 return serviceProvider;
350 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.ParseCanonicalName"]/*' />
351 protected virtual int ParseCanonicalName(string name, out uint itemId)
353 return innerVsHierarchy.ParseCanonicalName(name, out itemId);
356 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.QueryClose"]/*' />
357 protected virtual bool QueryClose()
359 int canClose;
360 NativeMethods.ThrowOnFailure(innerVsHierarchy.QueryClose(out canClose));
361 return (canClose != 0);
364 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SetGuidProperty"]/*' />
365 protected virtual void SetGuidProperty(uint itemId, int propId, ref System.Guid guid)
367 NativeMethods.ThrowOnFailure(innerVsHierarchy.SetGuidProperty(itemId, propId, ref guid));
370 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.UnadviseHierarchyEvents"]/*' />
371 protected virtual void UnadviseHierarchyEvents(uint cookie)
373 NativeMethods.ThrowOnFailure(innerVsHierarchy.UnadviseHierarchyEvents(cookie));
376 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SetProperty"]/*' />
377 protected virtual int SetProperty(uint itemId, int propId, System.Object property)
379 return innerVsHierarchy.SetProperty(itemId, propId, property);
382 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Unused0"]/*' />
383 protected virtual void Unused0()
385 NativeMethods.ThrowOnFailure(innerVsHierarchy.Unused0());
388 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Unused1"]/*' />
389 protected virtual void Unused1()
391 NativeMethods.ThrowOnFailure(innerVsHierarchy.Unused1());
394 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Unused2"]/*' />
395 protected virtual void Unused2()
397 NativeMethods.ThrowOnFailure(innerVsHierarchy.Unused2());
400 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Unused3"]/*' />
401 protected virtual void Unused3()
403 NativeMethods.ThrowOnFailure(innerVsHierarchy.Unused3());
406 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.Unused4"]/*' />
407 protected virtual void Unused4()
409 NativeMethods.ThrowOnFailure(innerVsHierarchy.Unused4());
411 #endregion
413 #region IVsUIHierarchy Members
415 // All methods (except for QueryStatusCommand and ExecCommand) call the IVsHierarchy implementation.
416 // QueryStatusCommand and ExecCommand call a protected virtual method that the base class can override.
417 // Note that we QI for IVsUIHierarchy on this so that if we are flavored we call the outer IVsHierarchy.
420 int IVsUIHierarchy.QueryStatusCommand(uint itemid, ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
422 return this.QueryStatusCommand(itemid, ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
424 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.QueryStatusCommand"]/*' />
425 protected virtual int QueryStatusCommand(uint itemid, ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
427 return innerVsUIHierarchy.QueryStatusCommand(itemid, ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
430 int IVsUIHierarchy.ExecCommand(uint itemid, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
432 return this.ExecCommand(itemid, ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
434 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.ExecCommand"]/*' />
435 protected virtual int ExecCommand(uint itemid, ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
437 return innerVsUIHierarchy.ExecCommand(itemid, ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
442 int IVsUIHierarchy.AdviseHierarchyEvents(IVsHierarchyEvents pEventSink, out uint pdwCookie)
444 return ((IVsHierarchy)this).AdviseHierarchyEvents(pEventSink, out pdwCookie);
447 int IVsUIHierarchy.Close()
449 return ((IVsHierarchy)this).Close();
452 int IVsUIHierarchy.GetCanonicalName(uint itemid, out string pbstrName)
454 return ((IVsHierarchy)this).GetCanonicalName(itemid, out pbstrName);
457 int IVsUIHierarchy.GetGuidProperty(uint itemid, int propid, out Guid pguid)
459 return ((IVsHierarchy)this).GetGuidProperty(itemid, propid, out pguid);
462 int IVsUIHierarchy.GetNestedHierarchy(uint itemid, ref Guid iidHierarchyNested, out IntPtr ppHierarchyNested, out uint pitemidNested)
464 return ((IVsHierarchy)this).GetNestedHierarchy(itemid, ref iidHierarchyNested, out ppHierarchyNested, out pitemidNested);
467 int IVsUIHierarchy.GetProperty(uint itemid, int propid, out object pvar)
469 return ((IVsHierarchy)this).GetProperty(itemid, propid, out pvar);
472 int IVsUIHierarchy.GetSite(out Microsoft.VisualStudio.OLE.Interop.IServiceProvider ppSP)
474 return ((IVsHierarchy)this).GetSite(out ppSP);
477 int IVsUIHierarchy.ParseCanonicalName(string pszName, out uint pitemid)
479 return ((IVsHierarchy)this).ParseCanonicalName(pszName, out pitemid);
482 int IVsUIHierarchy.QueryClose(out int pfCanClose)
484 return ((IVsHierarchy)this).QueryClose(out pfCanClose);
487 int IVsUIHierarchy.SetGuidProperty(uint itemid, int propid, ref Guid rguid)
489 return ((IVsHierarchy)this).SetGuidProperty(itemid, propid, ref rguid);
492 int IVsUIHierarchy.SetProperty(uint itemid, int propid, object var)
494 return ((IVsHierarchy)this).SetProperty(itemid, propid, var);
497 int IVsUIHierarchy.SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider psp)
499 return ((IVsHierarchy)this).SetSite(psp);
502 int IVsUIHierarchy.UnadviseHierarchyEvents(uint dwCookie)
504 return ((IVsHierarchy)this).UnadviseHierarchyEvents(dwCookie);
507 int IVsUIHierarchy.Unused0()
509 return ((IVsHierarchy)this).Unused0();
512 int IVsUIHierarchy.Unused1()
514 return ((IVsHierarchy)this).Unused1();
517 int IVsUIHierarchy.Unused2()
519 return ((IVsHierarchy)this).Unused2();
522 int IVsUIHierarchy.Unused3()
524 return ((IVsHierarchy)this).Unused3();
527 int IVsUIHierarchy.Unused4()
529 return ((IVsHierarchy)this).Unused4();
532 #endregion
535 #region IOleCommandTarget Members
537 int IOleCommandTarget.Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
539 int hr = ((IOleCommandTarget)menuService).Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
540 return hr;
543 int IOleCommandTarget.QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
545 int hr = ((IOleCommandTarget)menuService).QueryStatus(ref pguidCmdGroup, cCmds, prgCmds, pCmdText);
546 return hr;
549 #endregion
551 #region IServiceProvider Members
553 object System.IServiceProvider.GetService(Type serviceType)
555 if (serviceType == typeof(IOleCommandTarget))
556 return ((IOleCommandTarget)menuService);
557 else if (serviceType == typeof(System.ComponentModel.Design.IMenuCommandService))
558 return ((System.ComponentModel.Design.IMenuCommandService)menuService);
559 else
560 return this.serviceProvider.GetService(serviceType);
564 #endregion
566 #region Events (subset of IVsTrackProjectDocumentsEvents)
567 // This makes it easier for the derived class to subscribe to only the events it
568 // is really interested in and get one event per file. This also filter events
569 // and only send events that have to do with this project
571 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.EventHandler"]/*' />
572 public delegate void EventHandler<ProjectDocumentsChangeEventArgs>(object sender, ProjectDocumentsChangeEventArgs e);
574 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FileAdded"]/*' />
575 /// <devdoc>
576 /// Called after a file was added to this project.
577 /// </devdoc>
578 public event EventHandler<ProjectDocumentsChangeEventArgs> FileAdded;
579 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FileRemoved"]/*' />
580 /// <devdoc>
581 /// Called after a file was remove from this project.
582 /// </devdoc>
583 public event EventHandler<ProjectDocumentsChangeEventArgs> FileRemoved;
584 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FileRenamed"]/*' />
585 /// <devdoc>
586 /// Called after a file was renamed in this project.
587 /// </devdoc>
588 public event EventHandler<ProjectDocumentsChangeEventArgs> FileRenamed;
590 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryAdded"]/*' />
591 /// <devdoc>
592 /// Called after a directory was added to this project.
593 /// </devdoc>
594 public event EventHandler<ProjectDocumentsChangeEventArgs> DirectoryAdded;
595 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryRemoved"]/*' />
596 /// <devdoc>
597 /// Called after a directory was remove from this project.
598 /// </devdoc>
599 public event EventHandler<ProjectDocumentsChangeEventArgs> DirectoryRemoved;
600 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryRenamed"]/*' />
601 /// <devdoc>
602 /// Called after a directory was renamed in this project.
603 /// </devdoc>
604 public event EventHandler<ProjectDocumentsChangeEventArgs> DirectoryRenamed;
606 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SccStatusChanged"]/*' />
607 /// <devdoc>
608 /// Called after the source code control status of a file in this project changed.
609 /// </devdoc>
610 public event EventHandler<ProjectDocumentsChangeEventArgs> SccStatusChanged;
611 #endregion
613 #region IVsTrackProjectDocumentsEvents2 Members
614 /// We subscribes to IVsTrackProjectDocumentsEvents and trigger the
615 /// corresponding event once per file per event.
616 /// We filters the events to only reports those related to our project.
617 /// This is NOT required for flavoring, but simplify the work the
618 /// derived classes have to do when subscribing to these events
620 int IVsTrackProjectDocumentsEvents2.OnAfterAddDirectoriesEx(int cProjects, int cDirectories, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSADDDIRECTORYFLAGS[] rgFlags)
622 GenerateEvents(rgpProjects, rgFirstIndices, rgpszMkDocuments, DirectoryAdded, new ProjectDocumentsChangeEventArgs());
623 return NativeMethods.S_OK;
626 int IVsTrackProjectDocumentsEvents2.OnAfterAddFilesEx(int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSADDFILEFLAGS[] rgFlags)
628 GenerateEvents(rgpProjects, rgFirstIndices, rgpszMkDocuments, FileAdded, new ProjectDocumentsChangeEventArgs());
629 return NativeMethods.S_OK;
632 int IVsTrackProjectDocumentsEvents2.OnAfterRemoveDirectories(int cProjects, int cDirectories, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSREMOVEDIRECTORYFLAGS[] rgFlags)
634 GenerateEvents(rgpProjects, rgFirstIndices, rgpszMkDocuments, DirectoryRemoved, new ProjectDocumentsChangeEventArgs());
635 return NativeMethods.S_OK;
638 int IVsTrackProjectDocumentsEvents2.OnAfterRemoveFiles(int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, VSREMOVEFILEFLAGS[] rgFlags)
640 GenerateEvents(rgpProjects, rgFirstIndices, rgpszMkDocuments, FileRemoved, new ProjectDocumentsChangeEventArgs());
641 return NativeMethods.S_OK;
644 int IVsTrackProjectDocumentsEvents2.OnAfterRenameDirectories(int cProjects, int cDirs, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgszMkOldNames, string[] rgszMkNewNames, VSRENAMEDIRECTORYFLAGS[] rgFlags)
646 GenerateEvents(rgpProjects, rgFirstIndices, rgszMkNewNames, DirectoryRenamed, new ProjectDocumentsChangeEventArgs());
647 return NativeMethods.S_OK;
650 int IVsTrackProjectDocumentsEvents2.OnAfterRenameFiles(int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgszMkOldNames, string[] rgszMkNewNames, VSRENAMEFILEFLAGS[] rgFlags)
652 GenerateEvents(rgpProjects, rgFirstIndices, rgszMkNewNames, FileRenamed, new ProjectDocumentsChangeEventArgs());
653 return NativeMethods.S_OK;
656 int IVsTrackProjectDocumentsEvents2.OnAfterSccStatusChanged(int cProjects, int cFiles, IVsProject[] rgpProjects, int[] rgFirstIndices, string[] rgpszMkDocuments, uint[] rgdwSccStatus)
658 GenerateEvents(rgpProjects, rgFirstIndices, rgpszMkDocuments, SccStatusChanged, new ProjectDocumentsChangeEventArgs());
659 return NativeMethods.S_OK;
662 int IVsTrackProjectDocumentsEvents2.OnQueryAddDirectories(IVsProject pProject, int cDirectories, string[] rgpszMkDocuments, VSQUERYADDDIRECTORYFLAGS[] rgFlags, VSQUERYADDDIRECTORYRESULTS[] pSummaryResult, VSQUERYADDDIRECTORYRESULTS[] rgResults)
664 return NativeMethods.S_OK; // We are not interested in this one
667 int IVsTrackProjectDocumentsEvents2.OnQueryAddFiles(IVsProject pProject, int cFiles, string[] rgpszMkDocuments, VSQUERYADDFILEFLAGS[] rgFlags, VSQUERYADDFILERESULTS[] pSummaryResult, VSQUERYADDFILERESULTS[] rgResults)
669 return NativeMethods.S_OK; // We are not interested in this one
672 int IVsTrackProjectDocumentsEvents2.OnQueryRemoveDirectories(IVsProject pProject, int cDirectories, string[] rgpszMkDocuments, VSQUERYREMOVEDIRECTORYFLAGS[] rgFlags, VSQUERYREMOVEDIRECTORYRESULTS[] pSummaryResult, VSQUERYREMOVEDIRECTORYRESULTS[] rgResults)
674 return NativeMethods.S_OK; // We are not interested in this one
677 int IVsTrackProjectDocumentsEvents2.OnQueryRemoveFiles(IVsProject pProject, int cFiles, string[] rgpszMkDocuments, VSQUERYREMOVEFILEFLAGS[] rgFlags, VSQUERYREMOVEFILERESULTS[] pSummaryResult, VSQUERYREMOVEFILERESULTS[] rgResults)
679 return NativeMethods.S_OK; // We are not interested in this one
682 int IVsTrackProjectDocumentsEvents2.OnQueryRenameDirectories(IVsProject pProject, int cDirs, string[] rgszMkOldNames, string[] rgszMkNewNames, VSQUERYRENAMEDIRECTORYFLAGS[] rgFlags, VSQUERYRENAMEDIRECTORYRESULTS[] pSummaryResult, VSQUERYRENAMEDIRECTORYRESULTS[] rgResults)
684 return NativeMethods.S_OK; // We are not interested in this one
687 int IVsTrackProjectDocumentsEvents2.OnQueryRenameFiles(IVsProject pProject, int cFiles, string[] rgszMkOldNames, string[] rgszMkNewNames, VSQUERYRENAMEFILEFLAGS[] rgFlags, VSQUERYRENAMEFILERESULTS[] pSummaryResult, VSQUERYRENAMEFILERESULTS[] rgResults)
689 return NativeMethods.S_OK; // We are not interested in this one
692 #endregion
694 #region Helpers for IVsTrackProjectDocumentsEvents2
696 /// <devdoc>
697 /// Used to subscribe/unsubscribe to those events
698 /// </devdoc>
699 private IVsTrackProjectDocuments2 GetTrackProjectDocuments()
701 IVsTrackProjectDocuments2 trackDocuments = ((System.IServiceProvider)this).GetService(typeof(SVsTrackProjectDocuments)) as IVsTrackProjectDocuments2;
702 if (trackDocuments == null)
704 throw new ApplicationException(SR.GetString(SR.Flavor_FailedToGetService, "SVsTrackProjectDocuments"));
706 return trackDocuments;
709 /// <devdoc>
710 /// Look at the list of projects and files and for each file that is part of this
711 /// project, set the MkDocument on the event argument and trigger the event.
712 /// </devdoc>
713 private void GenerateEvents(
714 IVsProject[] projects,
715 int[] firstFiles,
716 string[] mkDocuments,
717 EventHandler<ProjectDocumentsChangeEventArgs> eventToGenerate,
718 ProjectDocumentsChangeEventArgs e)
720 if (eventToGenerate == null)
721 return; // no event = nothing to do
723 if (projects == null || firstFiles == null || mkDocuments == null)
724 throw new ArgumentNullException();
725 if (projects.Length != firstFiles.Length)
726 throw new ArgumentException();
728 // First find out which range of the array (if any) include the files that belong to this project
729 int first = -1;
730 int last = mkDocuments.Length - 1; // default to the last document
731 for (int i = 0; i < projects.Length; ++i)
733 if (first > -1)
735 // We get here if there is 1 or more project(s) after ours in the list
736 last = firstFiles[i] - 1;
737 break;
739 if (Object.ReferenceEquals(projects[i], this))
740 first = firstFiles[i];
742 if (last >= mkDocuments.Length)
743 throw new ArgumentException();
744 // See if we have any documents
745 if (first < 0)
746 return; // Nothing that belongs to this project
748 // For each file, generate the event
749 for (int i = first; i <= last; ++i)
753 e.MkDocument = mkDocuments[i];
754 eventToGenerate(this, e);
756 catch(Exception error)
758 Debug.Fail(error.Message);
762 #endregion