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
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"]/*' />
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.
25 public abstract class FlavoredProject
:
26 Microsoft
.VisualStudio
.ProjectAggregator
.CProjectAggregatorClass
, // Provide aggregation support
27 IVsAggregatableProject
,
28 System
.IServiceProvider
,
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
;
52 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FlavoredProject"]/*' />
53 public FlavoredProject()
57 #region IVsAggregatableProject
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
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"]/*' />
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
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
98 /// Do the initialization here (such as loading flavor specific
99 /// information from the project)
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
);
111 this.InitializeForOuter(fileName
, location
, name
, flags
, ref guidProject
, out cancel
);
115 return NativeMethods
.S_OK
;
118 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.InitializeForOuter"]/*' />
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
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
)
130 /// This is called when all object in aggregation have received InitializeForOuter calls.
131 /// At this point the aggregation is complete and fully functional.
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"]/*' />
143 /// This is called when all object in aggregation have received InitializeForOuter calls.
144 /// At this point the aggregation is complete and fully functional.
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
));
156 /// This must be delegetated to the inner most project
158 int IVsAggregatableProject
.SetAggregateProjectTypeGuids(string projectTypeGuids
)
160 if (innerVsAggregatableProject
== null)
161 throw new NotSupportedException();
163 return innerVsAggregatableProject
.SetAggregateProjectTypeGuids(projectTypeGuids
);
167 /// This must be delegetated to the inner most project
169 int IVsAggregatableProject
.GetAggregateProjectTypeGuids(out string projectTypeGuids
)
171 if (innerVsAggregatableProject
== null)
172 throw new NotSupportedException();
174 return innerVsAggregatableProject
.GetAggregateProjectTypeGuids(out projectTypeGuids
);
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
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()
196 // Unsubscribe to events
197 IVsTrackProjectDocuments2 trackDocuments
= GetTrackProjectDocuments();
198 Debug
.Assert(ErrorHandler
.Succeeded(trackDocuments
.UnadviseTrackProjectDocumentsEvents(cookie
)), "Failed to UnadviseTrackProjectDocumentsEvents");
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
)
243 if (this.QueryClose())
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()
275 return NativeMethods
.S_OK
;
278 int IVsHierarchy
.Unused1()
281 return NativeMethods
.S_OK
;
284 int IVsHierarchy
.Unused2()
287 return NativeMethods
.S_OK
;
290 int IVsHierarchy
.Unused3()
293 return NativeMethods
.S_OK
;
296 int IVsHierarchy
.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
)
306 NativeMethods
.ThrowOnFailure(innerVsHierarchy
.AdviseHierarchyEvents(eventSink
, out 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
)
326 NativeMethods
.ThrowOnFailure(innerVsHierarchy
.GetGuidProperty(itemId
, propId
, out 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()
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());
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();
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
);
543 int IOleCommandTarget
.QueryStatus(ref Guid pguidCmdGroup
, uint cCmds
, OLECMD
[] prgCmds
, IntPtr pCmdText
)
545 int hr
= ((IOleCommandTarget
)menuService
).QueryStatus(ref pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
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
);
560 return this.serviceProvider
.GetService(serviceType
);
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"]/*' />
576 /// Called after a file was added to this project.
578 public event EventHandler
<ProjectDocumentsChangeEventArgs
> FileAdded
;
579 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FileRemoved"]/*' />
581 /// Called after a file was remove from this project.
583 public event EventHandler
<ProjectDocumentsChangeEventArgs
> FileRemoved
;
584 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.FileRenamed"]/*' />
586 /// Called after a file was renamed in this project.
588 public event EventHandler
<ProjectDocumentsChangeEventArgs
> FileRenamed
;
590 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryAdded"]/*' />
592 /// Called after a directory was added to this project.
594 public event EventHandler
<ProjectDocumentsChangeEventArgs
> DirectoryAdded
;
595 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryRemoved"]/*' />
597 /// Called after a directory was remove from this project.
599 public event EventHandler
<ProjectDocumentsChangeEventArgs
> DirectoryRemoved
;
600 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.DirectoryRenamed"]/*' />
602 /// Called after a directory was renamed in this project.
604 public event EventHandler
<ProjectDocumentsChangeEventArgs
> DirectoryRenamed
;
606 /// <include file='doc\FlavoredProject.uex' path='docs/doc[@for="FlavoredProject.SccStatusChanged"]/*' />
608 /// Called after the source code control status of a file in this project changed.
610 public event EventHandler
<ProjectDocumentsChangeEventArgs
> SccStatusChanged
;
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
694 #region Helpers for IVsTrackProjectDocumentsEvents2
697 /// Used to subscribe/unsubscribe to those events
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
;
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.
713 private void GenerateEvents(
714 IVsProject
[] projects
,
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
730 int last
= mkDocuments
.Length
- 1; // default to the last document
731 for (int i
= 0; i
< projects
.Length
; ++i
)
735 // We get here if there is 1 or more project(s) after ours in the list
736 last
= firstFiles
[i
] - 1;
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
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
);