Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: obsolete/Microsoft.VisualStudio.Project/HierarchyNode.cs

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /// Copyright (c) Microsoft Corporation. All rights reserved.
2
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Diagnostics;
7 using System.Diagnostics.CodeAnalysis;
8 using System.Globalization;
9 using System.IO;
10 using System.Runtime.InteropServices;
11 using System.Text;
12 using Microsoft.VisualStudio;
13 using Microsoft.VisualStudio.OLE.Interop;
14 using Microsoft.VisualStudio.Shell;
15 //#define CCI_TRACING
16 using Microsoft.VisualStudio.Shell.Interop;
17 using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants;
18 using ShellConstants = Microsoft.VisualStudio.Shell.Interop.Constants;
19 using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
20 using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
21
22 namespace Microsoft.VisualStudio.Project
23 {
24 /// <summary>
25 /// An object that deals with user interaction via a GUI in the form a h ierarchy: a parent node with zero or more child nodes, each of which
26 /// can itself be a hierarchy.
27 /// </summary>
28 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainabil ity", "CA1506:AvoidExcessiveClassCoupling"), CLSCompliant(false), ComVisible(tru e)]
29 public abstract class HierarchyNode :
30 IVsUIHierarchy,
31 IVsPersistHierarchyItem2,
32 Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget,
33 IVsHierarchyDropDataSource2,
34 IVsHierarchyDropDataSource,
35 IVsHierarchyDropDataTarget,
36 IVsHierarchyDeleteHandler,
37 IDisposable
38 //, IVsBuildStatusCallback
39 {
40 #region nested types
41 /// <summary>
42 /// DropEffect as defined in oleidl.h
43 /// </summary>
44 internal enum DropEffect
45 {
46 None,
47 Copy = 1,
48 Move = 2,
49 Link = 4
50 };
51 #endregion
52
53 #region Events
54 internal event EventHandler<HierarchyNodeEventArgs> OnChildAdded
55 {
56 add { onChildAdded += value; }
57 remove { onChildAdded -= value; }
58 }
59 internal event EventHandler<HierarchyNodeEventArgs> OnChildRemov ed
60 {
61 add { onChildRemoved += value; }
62 remove { onChildRemoved -= value; }
63 }
64 #endregion
65
66 #region static/const fields
67 public static readonly Guid SolutionExplorer = new Guid(EnvDTE.C onstants.vsWindowKindSolutionExplorer);
68 public const int NoImage = -1;
69 #if DEBUG
70 internal static int LastTracedProperty;
71 #endif
72 #endregion
73
74 #region fields
75 private EventSinkCollection hierarchyEventSinks = new EventSinkC ollection();
76 private ProjectNode projectMgr;
77 private ProjectElement itemNode;
78 private HierarchyNode parentNode;
79 private HierarchyNode nextSibling;
80 private HierarchyNode firstChild;
81 private HierarchyNode lastChild;
82 private bool isExpanded;
83 private uint hierarchyId;
84 private uint docCookie;
85 private bool hasDesigner;
86 private string virtualNodeName = String.Empty; // Only used by virtual nodes
87 private IVsHierarchy parentHierarchy;
88 private int parentHierarchyItemId;
89 private NodeProperties nodeProperties;
90 private OleServiceProvider oleServiceProvider = new OleServicePr ovider();
91 private bool excludeNodeFromScc;
92 private EventHandler<HierarchyNodeEventArgs> onChildAdded;
93 private EventHandler<HierarchyNodeEventArgs> onChildRemoved;
94 private bool hasParentNodeNameRelation;
95 private List<HierarchyNode> itemsDraggedOrCutOrCopied;
96 private bool sourceDraggedOrCutOrCopied;
97
98 /// <summary>
99 /// Has the object been disposed.
100 /// </summary>
101 /// <devremark>We will not specify a property for isDisposed, ra ther it is expected that the a private flag is defined
102 /// on all subclasses. We do not want get in a situation where t he base class's dipose is not called because a child sets the flag through the p roperty.</devremark>
103 private bool isDisposed;
104 #endregion
105
106 #region abstract properties
107 /// <summary>
108 /// The URL of the node.
109 /// </summary>
110 /// <value></value>
111 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Desi gn", "CA1056:UriPropertiesShouldNotBeStrings")]
112 public abstract string Url
113 {
114 get;
115 }
116
117 /// <summary>
118 /// The Caption of the node.
119 /// </summary>
120 /// <value></value>
121 public abstract string Caption
122 {
123 get;
124 }
125
126 /// <summary>
127 /// The item type guid associated to a node.
128 /// </summary>
129 /// <value></value>
130 public abstract Guid ItemTypeGuid
131 {
132 get;
133 }
134 #endregion
135
136 #region virtual properties
137 /// <summary>
138 /// Defines a string that is used to separate the name relation from the extension
139 /// </summary>
140 public virtual string NameRelationSeparator
141 {
142 get
143 {
144 return ".";
145 }
146 }
147
148
149 public virtual int MenuCommandId
150 {
151 get { return VsMenus.IDM_VS_CTXT_NOCOMMANDS; }
152 }
153
154
155 /// <summary>
156 /// Return an imageindex
157 /// </summary>
158 /// <returns></returns>
159 public virtual int ImageIndex
160 {
161 get { return NoImage; }
162 }
163
164 /// <summary>
165 /// Return an state icon index
166 /// </summary>
167 /// <returns></returns>
168 /// <summary>
169 /// Sets the state icon for a file.
170 /// </summary>
171 public virtual VsStateIcon StateIconIndex
172 {
173 get
174 {
175 if(!this.ExcludeNodeFromScc)
176 {
177 IVsSccManager2 sccManager = this.Project Mgr.Site.GetService(typeof(SVsSccManager)) as IVsSccManager2;
178
179 if(sccManager != null)
180 {
181 VsStateIcon[] statIcons = new Vs StateIcon[1] { VsStateIcon.STATEICON_NOSTATEICON };
182 uint[] sccStatus = new uint[1] { 0 };
183 // Get the glyph from the scc ma nager. Note that it will fail in command line
184 // scenarios.
185 if(ErrorHandler.Succeeded(sccMan ager.GetSccGlyph(1, new string[] { this.GetMkDocument() }, statIcons, sccStatus) ))
186 {
187 return statIcons[0];
188 }
189 }
190 }
191
192 return VsStateIcon.STATEICON_NOSTATEICON;
193 }
194 }
195
196 /// <summary>
197 /// Defines whether a node can execute a command if in selection .
198 /// </summary>
199 public virtual bool CanExecuteCommand
200 {
201 get
202 {
203 return true;
204 }
205 }
206
207 /// <summary>
208 /// Used to determine the sort order of different node types
209 /// in the solution explorer window.
210 /// Nodes with the same priorities are sorted based on their cap tions.
211 /// </summary>
212 public virtual int SortPriority
213 {
214 get { return DefaultSortOrderNode.HierarchyNode; }
215 }
216
217 /// <summary>
218 /// Defines the properties attached to this node.
219 /// </summary>
220 public virtual NodeProperties NodeProperties
221 {
222 get
223 {
224 if(null == nodeProperties)
225 {
226 nodeProperties = CreatePropertiesObject( );
227 }
228 return this.nodeProperties;
229 }
230
231 }
232
233 /// <summary>
234 /// Returns an object that is a special view over this object; t his is the value
235 /// returned by the Object property of the automation objects.
236 /// </summary>
237 internal virtual object Object
238 {
239 get { return this; }
240 }
241 #endregion
242
243 #region properties
244
245 public OleServiceProvider OleServiceProvider
246 {
247 get
248 {
249 return this.oleServiceProvider;
250 }
251 }
252
253 [System.ComponentModel.BrowsableAttribute(false)]
254 public ProjectNode ProjectMgr
255 {
256 get
257 {
258 return this.projectMgr;
259 }
260 set
261 {
262 this.projectMgr = value;
263 }
264 }
265
266
267 [System.ComponentModel.BrowsableAttribute(false)]
268 public HierarchyNode NextSibling
269 {
270 get
271 {
272 return this.nextSibling;
273 }
274 set
275 {
276 this.nextSibling = value;
277 }
278 }
279
280
281 [System.ComponentModel.BrowsableAttribute(false)]
282 public HierarchyNode FirstChild
283 {
284 get
285 {
286 return this.firstChild;
287 }
288 set
289 {
290 this.firstChild = value;
291 }
292 }
293
294 [System.ComponentModel.BrowsableAttribute(false)]
295 public HierarchyNode LastChild
296 {
297 get
298 {
299 return this.lastChild;
300 }
301 set
302 {
303 this.lastChild = value;
304 }
305 }
306
307
308 [System.ComponentModel.BrowsableAttribute(false)]
309 public HierarchyNode Parent
310 {
311 get
312 {
313 return this.parentNode;
314 }
315 set
316 {
317 this.parentNode = value;
318 }
319 }
320
321
322 [System.ComponentModel.BrowsableAttribute(false)]
323 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBe CasedCorrectly", MessageId = "ID")]
324 public uint ID
325 {
326 get
327 {
328 return this.hierarchyId;
329 }
330 internal set
331 {
332 this.hierarchyId = value;
333 }
334 }
335
336
337 [System.ComponentModel.BrowsableAttribute(false)]
338 public ProjectElement ItemNode
339 {
340 get
341 {
342 return itemNode;
343 }
344 set
345 {
346 itemNode = value;
347 }
348 }
349
350
351 [System.ComponentModel.BrowsableAttribute(false)]
352 public bool HasDesigner
353 {
354 get
355 {
356 return this.hasDesigner;
357 }
358 set { this.hasDesigner = value; }
359 }
360
361
362 [System.ComponentModel.BrowsableAttribute(false)]
363 public bool IsExpanded
364 {
365 get
366 {
367 return this.isExpanded;
368 }
369 set { this.isExpanded = value; }
370 }
371
372 public string VirtualNodeName
373 {
374 get
375 {
376 return this.virtualNodeName;
377 }
378 set
379 {
380 this.virtualNodeName = value;
381 }
382 }
383
384
385 [System.ComponentModel.BrowsableAttribute(false)]
386 public HierarchyNode PreviousSibling
387 {
388 get
389 {
390 if(this.parentNode == null) return null;
391 HierarchyNode prev = null;
392 for(HierarchyNode child = this.parentNode.firstC hild; child != null; child = child.nextSibling)
393 {
394 if(child == this)
395 break;
396 prev = child;
397 }
398 return prev;
399 }
400 }
401
402 public uint DocCookie
403 {
404 get
405 {
406 return this.docCookie;
407 }
408 set
409 {
410 this.docCookie = value;
411 }
412 }
413
414 /// <summary>
415 /// Specifies if a Node is under source control.
416 /// </summary>
417 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Scc")]
418 public bool ExcludeNodeFromScc
419 {
420 get
421 {
422 return this.excludeNodeFromScc;
423 }
424 set
425 {
426 this.excludeNodeFromScc = value;
427 }
428 }
429
430 /// <summary>
431 /// Defines if a node a name relation to its parent node
432 ///
433 /// </summary>
434 public bool HasParentNodeNameRelation
435 {
436 get
437 {
438 return this.hasParentNodeNameRelation;
439 }
440 set
441 {
442 this.hasParentNodeNameRelation = value;
443 }
444 }
445
446 protected bool SourceDraggedOrCutOrCopied
447 {
448 get
449 {
450 return this.sourceDraggedOrCutOrCopied;
451 }
452 set
453 {
454 this.sourceDraggedOrCutOrCopied = value;
455 }
456 }
457
458 protected IList<HierarchyNode> ItemsDraggedOrCutOrCopied
459 {
460 get
461 {
462 return this.itemsDraggedOrCutOrCopied;
463 }
464 }
465 #endregion
466
467 #region ctors
468
469 protected HierarchyNode()
470 {
471 this.IsExpanded = true;
472 }
473
474 protected HierarchyNode(ProjectNode root, ProjectElement element )
475 {
476 this.projectMgr = root;
477 this.itemNode = element;
478 this.hierarchyId = this.projectMgr.ItemIdMap.Add(this);
479 this.oleServiceProvider.AddService(typeof(IVsHierarchy), root, false);
480 }
481
482 /// <summary>
483 /// Overloaded ctor.
484 /// </summary>
485 /// <param name="root"></param>
486 protected HierarchyNode(ProjectNode root)
487 {
488 this.projectMgr = root;
489 this.itemNode = new ProjectElement(this.projectMgr, null , true);
490 this.hierarchyId = this.projectMgr.ItemIdMap.Add(this);
491 this.oleServiceProvider.AddService(typeof(IVsHierarchy), root, false);
492 }
493 #endregion
494
495 #region static methods
496 /// <summary>
497 /// Get the outer IVsHierarchy implementation.
498 /// This is used for scenario where a flavor may be modifying th e behavior
499 /// </summary>
500 internal static IVsHierarchy GetOuterHierarchy(HierarchyNode nod e)
501 {
502 IVsHierarchy hierarchy = null;
503 // The hierarchy of a node is its project node hierarchy
504 IntPtr projectUnknown = Marshal.GetIUnknownForObject(nod e.projectMgr);
505 try
506 {
507 hierarchy = (IVsHierarchy)Marshal.GetTypedObject ForIUnknown(projectUnknown, typeof(IVsHierarchy));
508 }
509 finally
510 {
511 if(projectUnknown != IntPtr.Zero)
512 {
513 Marshal.Release(projectUnknown);
514 }
515 }
516 return hierarchy;
517 }
518 #endregion
519
520 #region virtual methods
521 /// <summary>
522 /// Creates an object derived from NodeProperties that will be u sed to expose properties
523 /// spacific for this object to the property browser.
524 /// </summary>
525 /// <returns></returns>
526 protected virtual NodeProperties CreatePropertiesObject()
527 {
528 return null;
529 }
530
531 /// <summary>
532 /// Return an iconhandle
533 /// </summary>
534 /// <param name="open"></param>
535 /// <returns></returns>
536 public virtual object GetIconHandle(bool open)
537 {
538 return null;
539 }
540
541 /// <summary>
542 /// AddChild - add a node, sorted in the right location.
543 /// </summary>
544 /// <param name="node">The node to add.</param>
545 public virtual void AddChild(HierarchyNode node)
546 {
547 if(node == null)
548 {
549 throw new ArgumentNullException("node");
550 }
551
552 // make sure the node is in the map.
553 Object nodeWithSameID = this.projectMgr.ItemIdMap[node.h ierarchyId];
554 if(!Object.ReferenceEquals(node, nodeWithSameID as Hiera rchyNode))
555 {
556 if(nodeWithSameID == null && node.ID <= this.Pro jectMgr.ItemIdMap.Count)
557 { // reuse our hierarchy id if possible.
558 this.projectMgr.ItemIdMap.SetAt(node.hie rarchyId, this);
559 }
560 else
561 {
562 throw new InvalidOperationException();
563 }
564 }
565
566 HierarchyNode previous = null;
567 for(HierarchyNode n = this.firstChild; n != null; n = n. nextSibling)
568 {
569 if(this.ProjectMgr.CompareNodes(node, n) > 0) br eak;
570 previous = n;
571 }
572 // insert "node" after "previous".
573 if(previous != null)
574 {
575 node.nextSibling = previous.nextSibling;
576 previous.nextSibling = node;
577 if(previous == this.lastChild)
578 {
579 this.lastChild = node;
580 }
581 }
582 else
583 {
584 if(this.lastChild == null)
585 {
586 this.lastChild = node;
587 }
588 node.nextSibling = this.firstChild;
589 this.firstChild = node;
590 }
591 node.parentNode = this;
592 this.OnItemAdded(this, node);
593 }
594
595 /// <summary>
596 /// Removes a node from the hierarchy.
597 /// </summary>
598 /// <param name="node">The node to remove.</param>
599 public virtual void RemoveChild(HierarchyNode node)
600 {
601 if(node == null)
602 {
603 throw new ArgumentNullException("node");
604 }
605
606 this.projectMgr.ItemIdMap.Remove(node);
607
608 HierarchyNode last = null;
609 for(HierarchyNode n = this.firstChild; n != null; n = n. nextSibling)
610 {
611 if(n == node)
612 {
613 if(last != null)
614 {
615 last.nextSibling = n.nextSibling ;
616 }
617 if(n == this.lastChild)
618 {
619 if(last == this.lastChild)
620 {
621 this.lastChild = null;
622 }
623 else
624 {
625 this.lastChild = last;
626 }
627 }
628 if(n == this.firstChild)
629 {
630 this.firstChild = n.nextSibling;
631 }
632 return;
633 }
634 last = n;
635 }
636 throw new InvalidOperationException("Node not found");
637 }
638
639 /// <summary>
640 /// Returns an automation object representing this node
641 /// </summary>
642 /// <returns>The automation object</returns>
643 public virtual object GetAutomationObject()
644 {
645 return new Automation.OAProjectItem<HierarchyNode>(this. projectMgr.GetAutomationObject() as Automation.OAProject, this);
646 }
647
648 /// <summary>
649 /// Returns a property object based on a property id
650 /// </summary>
651 /// <param name="propId">the property id of the property request ed</param>
652 /// <returns>the property object requested</returns>
653 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Perf ormance", "CA1800:DoNotCastUnnecessarily"), System.Diagnostics.CodeAnalysis.Supp ressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
654 public virtual object GetProperty(int propId)
655 {
656 object result = null;
657 switch((__VSHPROPID)propId)
658 {
659 case __VSHPROPID.VSHPROPID_Expandable:
660 result = (this.firstChild != null);
661 break;
662
663 case __VSHPROPID.VSHPROPID_Caption:
664 result = this.Caption;
665 break;
666
667 case __VSHPROPID.VSHPROPID_Name:
668 result = this.Caption;
669 break;
670
671 case __VSHPROPID.VSHPROPID_ExpandByDefault:
672 result = false;
673 break;
674
675 case __VSHPROPID.VSHPROPID_IconImgList:
676 result = this.ProjectMgr.ImageHandler.Im ageList.Handle;
677 break;
678
679 case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
680 case __VSHPROPID.VSHPROPID_IconIndex:
681 int index = this.ImageIndex;
682 if(index != NoImage)
683 {
684 result = index;
685 }
686 break;
687
688 case __VSHPROPID.VSHPROPID_StateIconIndex:
689 result = (int)this.StateIconIndex;
690 break;
691
692 case __VSHPROPID.VSHPROPID_IconHandle:
693 result = GetIconHandle(false);
694 break;
695
696 case __VSHPROPID.VSHPROPID_OpenFolderIconHandle:
697 result = GetIconHandle(true);
698 break;
699
700 case __VSHPROPID.VSHPROPID_NextVisibleSibling:
701 goto case __VSHPROPID.VSHPROPID_NextSibl ing;
702
703 case __VSHPROPID.VSHPROPID_NextSibling:
704 result = (int)((this.nextSibling != null ) ? this.nextSibling.hierarchyId : VSConstants.VSITEMID_NIL);
705 break;
706
707 case __VSHPROPID.VSHPROPID_FirstChild:
708 goto case __VSHPROPID.VSHPROPID_FirstVis ibleChild;
709
710 case __VSHPROPID.VSHPROPID_FirstVisibleChild:
711 result = (int)((this.firstChild != null) ? this.firstChild.hierarchyId : VSConstants.VSITEMID_NIL);
712 break;
713
714 case __VSHPROPID.VSHPROPID_Parent:
715 if(null == this.parentNode)
716 {
717 unchecked { result = new IntPtr( (int)VSConstants.VSITEMID_NIL); }
718 }
719 else
720 {
721 result = new IntPtr((int)this.pa rentNode.hierarchyId); // see bug 176470
722 }
723 break;
724
725 case __VSHPROPID.VSHPROPID_ParentHierarchyItemid :
726 if(parentHierarchy != null)
727 {
728 result = (IntPtr)parentHierarchy ItemId; // VS requires VT_I4 | VT_INT_PTR
729 }
730 break;
731
732 case __VSHPROPID.VSHPROPID_ParentHierarchy:
733 result = parentHierarchy;
734 break;
735
736 case __VSHPROPID.VSHPROPID_Root:
737 result = Marshal.GetIUnknownForObject(th is.projectMgr);
738 break;
739
740 case __VSHPROPID.VSHPROPID_Expanded:
741 result = this.isExpanded;
742 break;
743
744 case __VSHPROPID.VSHPROPID_BrowseObject:
745 result = this.NodeProperties;
746 if(result != null) result = new Dispatch Wrapper(result);
747 break;
748
749 case __VSHPROPID.VSHPROPID_EditLabel:
750 if(this.ProjectMgr != null && !this.Proj ectMgr.IsClosed && !this.ProjectMgr.IsCurrentStateASuppressCommandsMode())
751 {
752 result = GetEditLabel();
753 }
754 break;
755
756 case __VSHPROPID.VSHPROPID_SaveName:
757 //SaveName is the name shown in the Save and the Save Changes dialog boxes.
758 result = this.Caption;
759 break;
760
761 case __VSHPROPID.VSHPROPID_ItemDocCookie:
762 if(this.docCookie != 0) return (IntPtr)t his.docCookie; //cast to IntPtr as some callers expect VT_INT
763 break;
764
765 case __VSHPROPID.VSHPROPID_ExtObject:
766 result = GetAutomationObject();
767 break;
768 }
769
770 __VSHPROPID2 id2 = (__VSHPROPID2)propId;
771 switch(id2)
772 {
773 case __VSHPROPID2.VSHPROPID_NoDefaultNestedHierS orting:
774 return true; // We are doing the sorting ourselves through VSHPROPID_FirstChild and VSHPROPID_NextSibling
775 case __VSHPROPID2.VSHPROPID_BrowseObjectCATID:
776 {
777 // If there is a browse object a nd it is a NodeProperties, then get it's CATID
778 object browseObject = this.GetPr operty((int)__VSHPROPID.VSHPROPID_BrowseObject);
779 if(browseObject != null)
780 {
781 if(browseObject is Dispa tchWrapper)
782 browseObject = ( (DispatchWrapper)browseObject).WrappedObject;
783 result = this.ProjectMgr .GetCATIDForType(browseObject.GetType()).ToString("B");
784 if(String.CompareOrdinal (result as string, Guid.Empty.ToString("B")) == 0)
785 result = null;
786 }
787 break;
788 }
789 case __VSHPROPID2.VSHPROPID_ExtObjectCATID:
790 {
791 // If there is a extensibility o bject and it is a NodeProperties, then get it's CATID
792 object extObject = this.GetPrope rty((int)__VSHPROPID.VSHPROPID_ExtObject);
793 if(extObject != null)
794 {
795 if(extObject is Dispatch Wrapper)
796 extObject = ((Di spatchWrapper)extObject).WrappedObject;
797 result = this.ProjectMgr .GetCATIDForType(extObject.GetType()).ToString("B");
798 if(String.CompareOrdinal (result as string, Guid.Empty.ToString("B")) == 0)
799 result = null;
800 }
801 break;
802 }
803 }
804 #if DEBUG
805 if(propId != LastTracedProperty)
806 {
807 string trailer = (result == null) ? "null" : res ult.ToString();
808 CCITracing.TraceCall(this.hierarchyId + "," + pr opId.ToString() + " = " + trailer);
809 LastTracedProperty = propId; // some basic filte ring here...
810 }
811 #endif
812 return result;
813 }
814
815 /// <summary>
816 /// Sets the value of a property for a given property id
817 /// </summary>
818 /// <param name="propid">the property id of the property to be s et</param>
819 /// <param name="value">value of the property</param>
820 /// <returns>S_OK if succeeded</returns>
821 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "propid")]
822 public virtual int SetProperty(int propid, object value)
823 {
824 __VSHPROPID id = (__VSHPROPID)propid;
825
826 CCITracing.TraceCall(this.hierarchyId + "," + id.ToStrin g());
827 switch(id)
828 {
829 case __VSHPROPID.VSHPROPID_Expanded:
830 this.isExpanded = (bool)value;
831 break;
832
833 case __VSHPROPID.VSHPROPID_ParentHierarchy:
834 parentHierarchy = (IVsHierarchy)value;
835 break;
836
837 case __VSHPROPID.VSHPROPID_ParentHierarchyItemid :
838 parentHierarchyItemId = (int)value;
839 break;
840
841 case __VSHPROPID.VSHPROPID_EditLabel:
842 return SetEditLabel((string)value);
843
844 default:
845 CCITracing.TraceCall(" unhandled");
846 break;
847 }
848 return VSConstants.S_OK;
849 }
850
851 /// <summary>
852 /// Get a guid property
853 /// </summary>
854 /// <param name="propid">property id for the guid property reque sted</param>
855 /// <param name="guid">the requested guid</param>
856 /// <returns>S_OK if succeded</returns>
857 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "propid")]
858 public virtual int GetGuidProperty(int propid, out Guid guid)
859 {
860 guid = Guid.Empty;
861 if(propid == (int)__VSHPROPID.VSHPROPID_TypeGuid)
862 {
863 guid = this.ItemTypeGuid;
864 }
865
866 if(guid.CompareTo(Guid.Empty) == 0)
867 {
868 return VSConstants.DISP_E_MEMBERNOTFOUND;
869 }
870
871 return VSConstants.S_OK;
872 }
873
874 /// <summary>
875 /// Set a guid property.
876 /// </summary>
877 /// <param name="propid">property id of the guid property to be set</param>
878 /// <param name="guid">the guid to be set</param>
879 /// <returns>E_NOTIMPL</returns>
880 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "propid")]
881 public virtual int SetGuidProperty(int propid, ref Guid guid)
882 {
883 return VSConstants.E_NOTIMPL;
884 }
885
886 /// <summary>
887 /// Called by the shell when a node has been renamed from the GU I
888 /// </summary>
889 /// <param name="label"></param>
890 /// <returns>E_NOTIMPL</returns>
891 public virtual int SetEditLabel(string label)
892 {
893 return VSConstants.E_NOTIMPL;
894 }
895
896 /// <summary>
897 /// Called by the shell to get the node caption when the user tr ies to rename from the GUI
898 /// </summary>
899 /// <returns>the node cation</returns>
900 public virtual string GetEditLabel()
901 {
902 return this.Caption;
903 }
904
905 /// <summary>
906 /// This method is called by the interface method GetMkDocument to specify the item moniker.
907 /// </summary>
908 /// <returns>The moniker for this item</returns>
909 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBe CasedCorrectly", MessageId = "Mk")]
910 public virtual string GetMkDocument()
911 {
912 return String.Empty;
913 }
914
915 /// <summary>
916 /// Removes items from the hierarchy. Project overwrites this
917 /// </summary>
918 /// <param name="removeFromStorage"></param>
919 public virtual void Remove(bool removeFromStorage)
920 {
921 string documentToRemove = this.GetMkDocument();
922
923 // Ask Document tracker listeners if we can remove the i tem.
924 string[] filesToBeDeleted = new string[1] { documentToRe move };
925 VSQUERYREMOVEFILEFLAGS[] queryRemoveFlags = this.GetQuer yRemoveFileFlags(filesToBeDeleted);
926 if(!this.ProjectMgr.Tracker.CanRemoveItems(filesToBeDele ted, queryRemoveFlags))
927 {
928 return;
929 }
930
931 // Close the document if it has a manager.
932 DocumentManager manager = this.GetDocumentManager();
933 if(manager != null)
934 {
935 if(manager.Close(!removeFromStorage ? __FRAMECLO SE.FRAMECLOSE_PromptSave : __FRAMECLOSE.FRAMECLOSE_NoSave) == VSConstants.E_ABOR T)
936 {
937 // User cancelled operation in message b ox.
938 return;
939 }
940 }
941
942 // Check out the project file.
943 if(!this.ProjectMgr.QueryEditProjectFile(false))
944 {
945 throw Marshal.GetExceptionForHR(VSConstants.OLE_ E_PROMPTSAVECANCELLED);
946 }
947
948 // Notify hierarchy event listeners that the file is goi ng to be removed.
949 OnItemDeleted();
950
951 // Remove child if any before removing from the hierarch y
952 for(HierarchyNode child = this.FirstChild; child != null ; child = child.NextSibling)
953 {
954 child.Remove(removeFromStorage);
955 }
956
957 // the project node has no parentNode
958 if(this.parentNode != null)
959 {
960 // Remove from the Hierarchy
961 this.parentNode.RemoveChild(this);
962 }
963
964 // We save here the path to delete since this.Url might call the Include which will be deleted by the RemoveFromProjectFile call.
965 string pathToDelete = this.GetMkDocument();
966 this.itemNode.RemoveFromProjectFile();
967
968 if(removeFromStorage)
969 {
970 this.DeleteFromStorage(pathToDelete);
971 }
972
973 // Close the document window if opened.
974 CloseDocumentWindow(this);
975
976 // Notify document tracker listeners that we have remove d the item.
977 VSREMOVEFILEFLAGS[] removeFlags = this.GetRemoveFileFlag s(filesToBeDeleted);
978 Debug.Assert(removeFlags != null, "At least an empty arr ay should be returned for the GetRemoveFileFlags");
979 this.ProjectMgr.Tracker.OnItemRemoved(documentToRemove, removeFlags[0]);
980
981 // Notify hierarchy event listeners that we have removed the item
982 if(null != this.parentNode.onChildRemoved)
983 {
984 HierarchyNodeEventArgs args = new HierarchyNodeE ventArgs(this);
985 parentNode.onChildRemoved(parentNode, args);
986 }
987
988 // Notify hierarchy event listeners that items have been invalidated
989 OnInvalidateItems(this.parentNode);
990
991 // Dispose the node now that is deleted.
992 this.Dispose(true);
993 }
994
995 /// <summary>
996 /// Returns the relational name which is defined as the first pa rt of the caption until indexof NameRelationSeparator
997 /// </summary>
998 public virtual string GetRelationalName()
999 {
1000 //Get the first part of the caption
1001 string[] partsOfParent = this.Caption.Split(new string[] { this.NameRelationSeparator }, StringSplitOptions.None);
1002 return partsOfParent[0];
1003 }
1004
1005 /// <summary>
1006 /// Returns the 'extension' of the relational name
1007 /// e.g. form1.resx returns .resx, form1.designer.cs returns .de signer.cs
1008 /// </summary>
1009 /// <returns>The extension</returns>
1010 public virtual string GetRelationNameExtension()
1011 {
1012 return this.Caption.Substring(this.Caption.IndexOf(this. NameRelationSeparator, StringComparison.Ordinal));
1013 }
1014
1015 /// <summary>
1016 /// Close open document frame for a specific node.
1017 /// </summary>
1018 protected void CloseDocumentWindow(HierarchyNode node)
1019 {
1020 // We walk the RDT looking for all running documents att ached to this hierarchy and itemid. There
1021 // are cases where there may be two different editors (n ot views) open on the same document.
1022 IEnumRunningDocuments pEnumRdt;
1023 IVsRunningDocumentTable pRdt = this.GetService(typeof(SV sRunningDocumentTable)) as IVsRunningDocumentTable;
1024 if(pRdt == null)
1025 {
1026 throw new InvalidOperationException();
1027 }
1028 if(ErrorHandler.Succeeded(pRdt.GetRunningDocumentsEnum(o ut pEnumRdt)))
1029 {
1030 uint[] cookie = new uint[1];
1031 uint fetched;
1032 uint saveOptions = (uint)__VSSLNSAVEOPTIONS.SLNS AVEOPT_NoSave;
1033 IVsHierarchy srpOurHier = node.projectMgr as IVs Hierarchy;
1034
1035 ErrorHandler.ThrowOnFailure(pEnumRdt.Reset());
1036 while(VSConstants.S_OK == pEnumRdt.Next(1, cooki e, out fetched))
1037 {
1038 // Note we can pass NULL for all paramet ers we don't care about
1039 uint empty;
1040 string emptyStr;
1041 IntPtr ppunkDocData;
1042 IVsHierarchy srpHier;
1043 uint itemid = VSConstants.VSITEMID_NIL;
1044
1045 ErrorHandler.ThrowOnFailure(pRdt.GetDocu mentInfo(
1046 cookie[0],
1047 out empty,
1048 out empty,
1049 out empty,
1050 out emptyStr,
1051 out srpHier,
1052 out itemid,
1053 out ppunkDocData));
1054
1055 // Is this one of our documents?
1056 if(Utilities.IsSameComObject(srpOurHier, srpHier) && itemid == node.ID)
1057 {
1058 IVsSolution soln = GetService(ty peof(SVsSolution)) as IVsSolution;
1059 ErrorHandler.ThrowOnFailure(soln .CloseSolutionElement(saveOptions, srpOurHier, cookie[0]));
1060 }
1061 if(ppunkDocData != IntPtr.Zero)
1062 Marshal.Release(ppunkDocData);
1063
1064 }
1065 }
1066 }
1067
1068 /// <summary>
1069 /// Redraws the state icon if the node is not excluded from sour ce control.
1070 /// </summary>
1071 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Scc")]
1072 protected internal virtual void UpdateSccStateIcons()
1073 {
1074 if(!this.ExcludeNodeFromScc)
1075 {
1076 this.ReDraw(UIHierarchyElement.SccState);
1077 }
1078 }
1079
1080 /// <summary>
1081 /// To be overwritten by descendants.
1082 /// </summary>
1083 protected internal virtual int SetEditLabel(string label, string relativePath)
1084 {
1085 throw new NotImplementedException();
1086 }
1087
1088 /// <summary>
1089 /// Called by the drag and drop implementation to ask the node
1090 /// which is being dragged/droped over which nodes should
1091 /// process the operation.
1092 /// This allows for dragging to a node that cannot contain
1093 /// items to let its parent accept the drop
1094 /// </summary>
1095 /// <returns>HierarchyNode that accept the drop handling</return s>
1096 protected internal virtual HierarchyNode GetDragTargetHandlerNod e()
1097 {
1098 return this;
1099 }
1100
1101 /// <summary>
1102 /// Add a new Folder to the project hierarchy.
1103 /// </summary>
1104 /// <returns>S_OK if succeeded, otherwise an error</returns>
1105 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Perf ormance", "CA1800:DoNotCastUnnecessarily")]
1106 protected virtual int AddNewFolder()
1107 {
1108 // Check out the project file.
1109 if(!this.ProjectMgr.QueryEditProjectFile(false))
1110 {
1111 throw Marshal.GetExceptionForHR(VSConstants.OLE_ E_PROMPTSAVECANCELLED);
1112 }
1113
1114 try
1115 {
1116 // Generate a new folder name
1117 string newFolderName;
1118 ErrorHandler.ThrowOnFailure(this.projectMgr.Gene rateUniqueItemName(this.hierarchyId, String.Empty, String.Empty, out newFolderNa me));
1119
1120 // create the project part of it, the project fi le
1121 HierarchyNode child = this.ProjectMgr.CreateFold erNodes(Path.Combine(this.virtualNodeName, newFolderName));
1122
1123 if(child is FolderNode)
1124 {
1125 ((FolderNode)child).CreateDirectory();
1126 }
1127
1128 // If we are in automation mode then skip the ui part which is about renaming the folder
1129 if(!Utilities.IsInAutomationFunction(this.projec tMgr.Site))
1130 {
1131 IVsUIHierarchyWindow uiWindow = UIHierar chyUtilities.GetUIHierarchyWindow(this.projectMgr.Site, SolutionExplorer);
1132 // we need to get into label edit mode n ow...
1133 // so first select the new guy...
1134 ErrorHandler.ThrowOnFailure(uiWindow.Exp andItem(this.projectMgr, child.hierarchyId, EXPANDFLAGS.EXPF_SelectItem));
1135 // them post the rename command to the s hell. Folder verification and creation will
1136 // happen in the setlabel code...
1137 IVsUIShell shell = this.projectMgr.Site. GetService(typeof(SVsUIShell)) as IVsUIShell;
1138
1139 Debug.Assert(shell != null, "Could not g et the ui shell from the project");
1140 if(shell == null)
1141 {
1142 return VSConstants.E_FAIL;
1143 }
1144
1145 object dummy = null;
1146 Guid cmdGroup = VsMenus.guidStandardComm andSet97;
1147 ErrorHandler.ThrowOnFailure(shell.PostEx ecCommand(ref cmdGroup, (uint)VsCommands.Rename, 0, ref dummy));
1148 }
1149 }
1150 catch(COMException e)
1151 {
1152 Trace.WriteLine("Exception : " + e.Message);
1153 return e.ErrorCode;
1154 }
1155
1156 return VSConstants.S_OK;
1157 }
1158
1159 protected virtual int AddItemToHierarchy(HierarchyAddType addTyp e)
1160 {
1161 CCITracing.TraceCall();
1162 IVsAddProjectItemDlg addItemDialog;
1163
1164 string strFilter = String.Empty;
1165 int iDontShowAgain;
1166 uint uiFlags;
1167 IVsProject3 project = (IVsProject3)this.projectMgr;
1168
1169 string strBrowseLocations = Path.GetDirectoryName(this.p rojectMgr.BaseURI.Uri.LocalPath);
1170
1171 System.Guid projectGuid = this.projectMgr.ProjectGuid;
1172
1173 addItemDialog = this.GetService(typeof(IVsAddProjectItem Dlg)) as IVsAddProjectItemDlg;
1174
1175 if(addType == HierarchyAddType.AddNewItem)
1176 uiFlags = (uint)(__VSADDITEMFLAGS.VSADDITEM_AddN ewItems | __VSADDITEMFLAGS.VSADDITEM_SuggestTemplateName | __VSADDITEMFLAGS.VSAD DITEM_AllowHiddenTreeView);
1177 else
1178 uiFlags = (uint)(__VSADDITEMFLAGS.VSADDITEM_AddE xistingItems | __VSADDITEMFLAGS.VSADDITEM_AllowMultiSelect | __VSADDITEMFLAGS.VS ADDITEM_AllowStickyFilter);
1179
1180 ErrorHandler.ThrowOnFailure(addItemDialog.AddProjectItem Dlg(this.hierarchyId, ref projectGuid, project, uiFlags, null, null, ref strBrow seLocations, ref strFilter, out iDontShowAgain)); /*&fDontShowAgain*/
1181
1182 return VSConstants.S_OK;
1183 }
1184
1185 /// <summary>
1186 /// Overwritten in subclasses
1187 /// </summary>
1188 protected virtual void DoDefaultAction()
1189 {
1190 CCITracing.TraceCall();
1191 }
1192
1193 /// <summary>
1194 /// Handles the exclude from project command.
1195 /// </summary>
1196 /// <returns></returns>
1197 protected virtual int ExcludeFromProject()
1198 {
1199 Debug.Assert(this.ProjectMgr != null, "The project item " + this.ToString() + " has not been initialised correctly. It has a null Projec tMgr");
1200 this.Remove(false);
1201 return VSConstants.S_OK;
1202 }
1203
1204 /// <summary>
1205 /// Handles the Show in Designer command.
1206 /// </summary>
1207 /// <returns></returns>
1208 protected virtual int ShowInDesigner(IList<HierarchyNode> select edNodes)
1209 {
1210 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1211 }
1212
1213 /// <summary>
1214 /// Prepares a selected node for clipboard.
1215 /// It takes the the project reference string of this item and a dds it to a stringbuilder.
1216 /// </summary>
1217 /// <returns>A stringbuilder.</returns>
1218 /// <devremark>This method has to be public since seleceted node s will call it.</devremark>
1219 [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShould BeCasedCorrectly", MessageId = "ClipBoard")]
1220 protected internal virtual StringBuilder PrepareSelectedNodesFor ClipBoard()
1221 {
1222 Debug.Assert(this.ProjectMgr != null, " No project manan ager available for this node " + ToString());
1223 Debug.Assert(this.ProjectMgr.ItemsDraggedOrCutOrCopied ! = null, " The itemsdragged list should have been initialized prior calling this method");
1224 StringBuilder sb = new StringBuilder();
1225
1226 if(this.hierarchyId == VSConstants.VSITEMID_ROOT)
1227 {
1228 if(this.ProjectMgr.ItemsDraggedOrCutOrCopied != null)
1229 {
1230 this.ProjectMgr.ItemsDraggedOrCutOrCopie d.Clear();// abort
1231 }
1232 return sb;
1233 }
1234
1235 if(this.ProjectMgr.ItemsDraggedOrCutOrCopied != null)
1236 {
1237 this.ProjectMgr.ItemsDraggedOrCutOrCopied.Add(th is);
1238 }
1239
1240 string projref = String.Empty;
1241 IVsSolution solution = this.GetService(typeof(IVsSolutio n)) as IVsSolution;
1242 if(solution != null)
1243 {
1244 ErrorHandler.ThrowOnFailure(solution.GetProjrefO fItem(this.ProjectMgr, this.hierarchyId, out projref));
1245 if(String.IsNullOrEmpty(projref))
1246 {
1247 if(this.ProjectMgr.ItemsDraggedOrCutOrCo pied != null)
1248 {
1249 this.ProjectMgr.ItemsDraggedOrCu tOrCopied.Clear();// abort
1250 }
1251 return sb;
1252 }
1253 }
1254
1255 // Append the projectref and a null terminator to the st ring builder
1256 sb.Append(projref);
1257 sb.Append('\0');
1258
1259 return sb;
1260 }
1261
1262 /// <summary>
1263 /// Returns the Cannonical Name
1264 /// </summary>
1265 /// <returns>Cannonical Name</returns>
1266 protected virtual string GetCanonicalName()
1267 {
1268 return this.GetMkDocument();
1269 }
1270
1271 /// <summary>
1272 /// Factory method for the Document Manager object
1273 /// </summary>
1274 /// <returns>null object, since a hierarchy node does not know i ts kind of document</returns>
1275 /// <remarks>Must be overriden by derived node classes if a docu ment manager is needed</remarks>
1276 protected internal virtual DocumentManager GetDocumentManager()
1277 {
1278 return null;
1279 }
1280
1281 /// <summary>
1282 /// Displays the context menu.
1283 /// </summary>
1284 /// <param name="selectedNodes">list of selected nodes.</param>
1285 /// <param name="pointerToVariant">contains the location (x,y) a t which to show the menu.</param>
1286 [SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNo tContainTypeNames", MessageId = "pointer")]
1287 protected virtual int DisplayContextMenu(IList<HierarchyNode> se lectedNodes, IntPtr pointerToVariant)
1288 {
1289 if(selectedNodes == null || selectedNodes.Count == 0 || pointerToVariant == IntPtr.Zero)
1290 {
1291 return NativeMethods.OLECMDERR_E_NOTSUPPORTED;
1292 }
1293
1294 int idmxStoredMenu = 0;
1295
1296 foreach(HierarchyNode node in selectedNodes)
1297 {
1298 // We check here whether we have a multiple sele ction of
1299 // nodes of differing type.
1300 if(idmxStoredMenu == 0)
1301 {
1302 // First time through or single node cas e
1303 idmxStoredMenu = node.MenuCommandId;
1304 }
1305 else if(idmxStoredMenu != node.MenuCommandId)
1306 {
1307 // We have different node types. Check i f any of the nodes is
1308 // the project node and set the menu acc ordingly.
1309 if(node.MenuCommandId == VsMenus.IDM_VS_ CTXT_PROJNODE)
1310 {
1311 idmxStoredMenu = VsMenus.IDM_VS_ CTXT_XPROJ_PROJITEM;
1312 }
1313 else
1314 {
1315 idmxStoredMenu = VsMenus.IDM_VS_ CTXT_XPROJ_MULTIITEM;
1316 }
1317 }
1318 }
1319
1320 object variant = Marshal.GetObjectForNativeVariant(point erToVariant);
1321 UInt32 pointsAsUint = (UInt32)variant;
1322 short x = (short)(pointsAsUint & 0x0000ffff);
1323 short y = (short)((pointsAsUint & 0xffff0000) / 0x10000) ;
1324
1325
1326 POINTS points = new POINTS();
1327 points.x = x;
1328 points.y = y;
1329 return ShowContextMenu(idmxStoredMenu, VsMenus.guidSHLMa inMenu, points);
1330 }
1331
1332 /// <summary>
1333 /// Shows the specified context menu at a specified location.
1334 /// </summary>
1335 /// <param name="menuId">The context menu ID.</param>
1336 /// <param name="groupGuid">The GUID of the menu group.</param>
1337 /// <param name="points">The location at which to show the menu. </param>
1338 protected virtual int ShowContextMenu(int menuId, Guid menuGroup , POINTS points)
1339 {
1340 IVsUIShell shell = this.projectMgr.Site.GetService(typeo f(SVsUIShell)) as IVsUIShell;
1341
1342 Debug.Assert(shell != null, "Could not get the ui shell from the project");
1343 if(shell == null)
1344 {
1345 return VSConstants.E_FAIL;
1346 }
1347 POINTS[] pnts = new POINTS[1];
1348 pnts[0].x = points.x;
1349 pnts[0].y = points.y;
1350 return shell.ShowContextMenu(0, ref menuGroup, menuId, p nts, (Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget)this);
1351 }
1352
1353 #region initiation of command execution
1354 /// <summary>
1355 /// Handles command execution.
1356 /// </summary>
1357 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1358 /// <param name="cmd">The command to be executed.</param>
1359 /// <param name="nCmdexecopt">Values describe how the object sho uld execute the command.</param>
1360 /// <param name="pvaIn">Pointer to a VARIANTARG structure contai ning input arguments. Can be NULL</param>
1361 /// <param name="pvaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
1362 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1363 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Cmdexecopt")]
1364 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "n")]
1365 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "pva")]
1366 protected virtual int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
1367 {
1368 if(this.projectMgr == null || this.projectMgr.IsClosed)
1369 {
1370 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1371 }
1372
1373 if(cmdGroup == Guid.Empty)
1374 {
1375 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1376 }
1377 else if(cmdGroup == VsMenus.guidVsUIHierarchyWindowCmds)
1378 {
1379 switch(cmd)
1380 {
1381 case (uint)VSConstants.VsUIHierarchyWind owCmdIds.UIHWCMDID_DoubleClick:
1382 case (uint)VSConstants.VsUIHierarchyWind owCmdIds.UIHWCMDID_EnterKey:
1383 this.DoDefaultAction();
1384 return VSConstants.S_OK;
1385 }
1386 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1387 }
1388 else if(cmdGroup == VsMenus.guidStandardCommandSet97)
1389 {
1390 HierarchyNode nodeToAddTo = this.GetDragTargetHa ndlerNode();
1391 switch((VsCommands)cmd)
1392 {
1393 case VsCommands.AddNewItem:
1394 return nodeToAddTo.AddItemToHier archy(HierarchyAddType.AddNewItem);
1395
1396 case VsCommands.AddExistingItem:
1397 return nodeToAddTo.AddItemToHier archy(HierarchyAddType.AddExistingItem);
1398
1399 case VsCommands.NewFolder:
1400 return nodeToAddTo.AddNewFolder( );
1401
1402 case VsCommands.Paste:
1403 return this.ProjectMgr.PasteFrom Clipboard(this);
1404 }
1405
1406 }
1407 else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1408 {
1409 switch((VsCommands2K)cmd)
1410 {
1411 case VsCommands2K.EXCLUDEFROMPROJECT:
1412 return this.ExcludeFromProject() ;
1413 }
1414 }
1415
1416 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1417 }
1418
1419 /// <summary>
1420 /// Executes a command that can only be executed once the whole selection is known.
1421 /// </summary>
1422 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1423 /// <param name="cmdId">The command to be executed.</param>
1424 /// <param name="cmdExecOpt">Values describe how the object shou ld execute the command.</param>
1425 /// <param name="vaIn">Pointer to a VARIANTARG structure contain ing input arguments. Can be NULL</param>
1426 /// <param name="vaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
1427 /// <param name="commandOrigin">The origin of the command. From IOleCommandTarget or hierarchy.</param>
1428 /// <param name="selectedNodes">The list of the selected nodes.< /param>
1429 /// <param name="handled">An out parameter specifying that the c ommand was handled.</param>
1430 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1431 [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShould BeCasedCorrectly", MessageId = "vaIn")]
1432 protected virtual int ExecCommandThatDependsOnSelectedNodes(Guid cmdGroup, uint cmdId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin commandOrigin, IList<HierarchyNode> selectedNodes, out bool handled)
1433 {
1434 handled = false;
1435 if(cmdGroup == VsMenus.guidVsUIHierarchyWindowCmds)
1436 {
1437 switch(cmdId)
1438 {
1439 case (uint)VSConstants.VsUIHierarchyWind owCmdIds.UIHWCMDID_RightClick:
1440 // The UIHWCMDID_RightClick is w hat tells an IVsUIHierarchy in a UIHierarchyWindow
1441 // to put up the context menu. Since the mouse may have moved between the
1442 // mouse down and the mouse up, GetCursorPos won't tell you the right place
1443 // to put the context menu (espe cially if it came through the keyboard).
1444 // So we pack the proper menu po sition into pvaIn by
1445 // memcpy'ing a POINTS struct in to the VT_UI4 part of the pvaIn variant. The
1446 // code to unpack it looks like this:
1447 // ULONG ul Pts = V_UI4(pvaIn);
1448 // POINTS p ts;
1449 // memcpy(( void*)&pts, &ulPts, sizeof(POINTS));
1450 // You then pass that POINTS int o DisplayContextMenu.
1451 handled = true;
1452 return this.DisplayContextMenu(s electedNodes, vaIn);
1453 default:
1454 break;
1455 }
1456 }
1457 else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1458 {
1459 switch((VsCommands2K)cmdId)
1460 {
1461 case VsCommands2K.ViewInClassDiagram:
1462 handled = true;
1463 return this.ShowInDesigner(selec tedNodes);
1464 }
1465 }
1466
1467 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1468 }
1469
1470 /// <summary>
1471 /// Executes command that are independent of a selection.
1472 /// </summary>
1473 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1474 /// <param name="cmdId">The command to be executed.</param>
1475 /// <param name="cmdExecOpt">Values describe how the object shou ld execute the command.</param>
1476 /// <param name="vaIn">Pointer to a VARIANTARG structure contain ing input arguments. Can be NULL</param>
1477 /// <param name="vaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
1478 /// <param name="commandOrigin">The origin of the command. From IOleCommandTarget or hierarchy.</param>
1479 /// <param name="handled">An out parameter specifying that the c ommand was handled.</param>
1480 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1481 [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShould BeCasedCorrectly", MessageId = "vaIn")]
1482 protected virtual int ExecCommandIndependentOfSelection(Guid cmd Group, uint cmdId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin com mandOrigin, out bool handled)
1483 {
1484 handled = false;
1485
1486 if(this.projectMgr == null || this.projectMgr.IsClosed)
1487 {
1488 return VSConstants.E_FAIL;
1489 }
1490
1491 if(cmdGroup == VsMenus.guidStandardCommandSet97)
1492 {
1493 if(commandOrigin == CommandOrigin.OleCommandTarg et)
1494 {
1495 switch((VsCommands)cmdId)
1496 {
1497 case VsCommands.Cut:
1498 case VsCommands.Copy:
1499 case VsCommands.Paste:
1500 case VsCommands.Rename:
1501 handled = true;
1502 return (int)OleConstants .OLECMDERR_E_NOTSUPPORTED;
1503 }
1504 }
1505
1506 switch((VsCommands)cmdId)
1507 {
1508 case VsCommands.Copy:
1509 handled = true;
1510 return this.ProjectMgr.CopyToCli pboard();
1511
1512 case VsCommands.Cut:
1513 handled = true;
1514 return this.ProjectMgr.CutToClip board();
1515
1516 case VsCommands.SolutionCfg:
1517 handled = true;
1518 return (int)OleConstants.OLECMDE RR_E_NOTSUPPORTED;
1519
1520 case VsCommands.SearchCombo:
1521 handled = true;
1522 return (int)OleConstants.OLECMDE RR_E_NOTSUPPORTED;
1523
1524 }
1525 }
1526 else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1527 {
1528 // There should only be the project node who han dles these and should manifest in the same action regardles of selection.
1529 switch((VsCommands2K)cmdId)
1530 {
1531 case VsCommands2K.SHOWALLFILES:
1532 handled = true;
1533 return this.projectMgr.ShowAllFi les();
1534 case VsCommands2K.ADDREFERENCE:
1535 handled = true;
1536 return this.projectMgr.AddProjec tReference();
1537 case VsCommands2K.ADDWEBREFERENCE:
1538 handled = true;
1539 return this.projectMgr.AddWebRef erence();
1540 }
1541 }
1542
1543 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1544 }
1545
1546 /// <summary>
1547 /// The main entry point for command excection. Gets called from the IVsUIHierarchy and IOleCommandTarget methods.
1548 /// </summary>
1549 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1550 /// <param name="cmdId">The command to be executed.</param>
1551 /// <param name="cmdExecOpt">Values describe how the object shou ld execute the command.</param>
1552 /// <param name="vaIn">Pointer to a VARIANTARG structure contain ing input arguments. Can be NULL</param>
1553 /// <param name="vaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
1554 /// <param name="commandOrigin">The origin of the command. From IOleCommandTarget or hierarchy.</param>
1555 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1556 [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShould BeCasedCorrectly", MessageId = "vaIn")]
1557 protected virtual int InternalExecCommand(Guid cmdGroup, uint cm dId, uint cmdExecOpt, IntPtr vaIn, IntPtr vaOut, CommandOrigin commandOrigin)
1558 {
1559 CCITracing.TraceCall(cmdGroup.ToString() + "," + cmdId.T oString());
1560 if(this.projectMgr == null || this.projectMgr.IsClosed)
1561 {
1562 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1563 }
1564
1565 if(cmdGroup == Guid.Empty)
1566 {
1567 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1568 }
1569
1570 IList<HierarchyNode> selectedNodes = this.projectMgr.Get SelectedNodes();
1571
1572 // Check if all nodes can execute a command. If there is at least one that cannot return not handled.
1573 foreach(HierarchyNode node in selectedNodes)
1574 {
1575 if(!node.CanExecuteCommand)
1576 {
1577 return (int)OleConstants.OLECMDERR_E_NOT SUPPORTED;
1578 }
1579 }
1580
1581 // Handle commands that are independent of a selection.
1582 bool handled = false;
1583 int returnValue = this.ExecCommandIndependentOfSelection (cmdGroup, cmdId, cmdExecOpt, vaIn, vaOut, commandOrigin, out handled);
1584 if(handled)
1585 {
1586 return returnValue;
1587 }
1588
1589
1590 // Now handle commands that need the selected nodes as i nput parameter.
1591 returnValue = this.ExecCommandThatDependsOnSelectedNodes (cmdGroup, cmdId, cmdExecOpt, vaIn, vaOut, commandOrigin, selectedNodes, out han dled);
1592 if(handled)
1593 {
1594 return returnValue;
1595 }
1596
1597 returnValue = (int)OleConstants.OLECMDERR_E_NOTSUPPORTED ;
1598
1599 // Handle commands iteratively. The same action will be executed for all of the selected items.
1600 foreach(HierarchyNode node in selectedNodes)
1601 {
1602 try
1603 {
1604 returnValue = node.ExecCommandOnNode(cmd Group, cmdId, cmdExecOpt, vaIn, vaOut);
1605 }
1606 catch(COMException e)
1607 {
1608 Trace.WriteLine("Exception : " + e.Messa ge);
1609 returnValue = e.ErrorCode;
1610 }
1611 if(returnValue != VSConstants.S_OK)
1612 {
1613 break;
1614 }
1615 }
1616
1617 if(returnValue == VSConstants.E_ABORT || returnValue == VSConstants.OLE_E_PROMPTSAVECANCELLED)
1618 {
1619 returnValue = VSConstants.S_OK;
1620 }
1621
1622 return returnValue;
1623 }
1624
1625 #endregion
1626
1627 #region query command handling
1628 /// <summary>
1629 /// Handles menus originating from IOleCommandTarget.
1630 /// </summary>
1631 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1632 /// <param name="cmd">The command to be executed.</param>
1633 /// <param name="handled">Specifies whether the menu was handled .</param>
1634 /// <returns>A QueryStatusResult describing the status of the me nu.</returns>
1635 protected virtual QueryStatusResult QueryStatusCommandFromOleCom mandTarget(Guid cmdGroup, uint cmd, out bool handled)
1636 {
1637 handled = false;
1638 // NOTE: We only want to support Cut/Copy/Paste/Delete/R ename commands
1639 // if focus is in the project window. This means that we should only
1640 // support these commands if they are dispatched via IVs UIHierarchy
1641 // interface and not if they are dispatch through IOleCo mmandTarget
1642 // during the command routing to the active project/hier archy.
1643 if(VsMenus.guidStandardCommandSet97 == cmdGroup)
1644 {
1645
1646 switch((VsCommands)cmd)
1647 {
1648 case VsCommands.Copy:
1649 case VsCommands.Paste:
1650 case VsCommands.Cut:
1651 case VsCommands.Rename:
1652 handled = true;
1653 return QueryStatusResult.NOTSUPP ORTED;
1654 }
1655 }
1656 // The reference menu and the web reference menu should always be shown.
1657 else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1658 {
1659 switch((VsCommands2K)cmd)
1660 {
1661 case VsCommands2K.ADDREFERENCE:
1662 handled = true;
1663 return QueryStatusResult.SUPPORT ED | QueryStatusResult.ENABLED;
1664 }
1665 }
1666 return QueryStatusResult.NOTSUPPORTED;
1667 }
1668
1669 /// <summary>
1670 /// Specifies which command does not support multiple selection and should be disabled if multi-selected.
1671 /// </summary>
1672 /// <param name="cmdGroup">Unique identifier of the command grou p</param>
1673 /// <param name="cmd">The command to be executed.</param>
1674 /// <param name="selectedNodes">The list of selected nodes.</par am>
1675 /// <param name="handled">Specifies whether the menu was handled .</param>
1676 /// <returns>A QueryStatusResult describing the status of the me nu.</returns>
1677 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Multi")]
1678 protected virtual QueryStatusResult DisableCommandOnNodesThatDoN otSupportMultiSelection(Guid cmdGroup, uint cmd, IList<HierarchyNode> selectedNo des, out bool handled)
1679 {
1680 handled = false;
1681 QueryStatusResult queryResult = QueryStatusResult.NOTSUP PORTED;
1682 if(selectedNodes == null || selectedNodes.Count == 1)
1683 {
1684 return queryResult;
1685 }
1686
1687 if(VsMenus.guidStandardCommandSet97 == cmdGroup)
1688 {
1689 switch((VsCommands)cmd)
1690 {
1691 case VsCommands.Cut:
1692 case VsCommands.Copy:
1693 // If the project node is select ed then cut and copy is not supported.
1694 if(selectedNodes.Contains(this.p rojectMgr))
1695 {
1696 queryResult = QueryStatu sResult.SUPPORTED | QueryStatusResult.INVISIBLE;
1697 handled = true;
1698 }
1699 break;
1700
1701 case VsCommands.Paste:
1702 case VsCommands.NewFolder:
1703 queryResult = QueryStatusResult. SUPPORTED | QueryStatusResult.INVISIBLE;
1704 handled = true;
1705 break;
1706 }
1707 }
1708 else if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1709 {
1710 switch((VsCommands2K)cmd)
1711 {
1712 case VsCommands2K.QUICKOBJECTSEARCH:
1713 case VsCommands2K.SETASSTARTPAGE:
1714 case VsCommands2K.ViewInClassDiagram:
1715 queryResult = QueryStatusResult. SUPPORTED | QueryStatusResult.INVISIBLE;
1716 handled = true;
1717 break;
1718 }
1719 }
1720
1721 return queryResult;
1722 }
1723
1724 /// <summary>
1725 /// Handles command status on a node. Should be overridden by de scendant nodes. If a command cannot be handled then the base should be called.
1726 /// </summary>
1727 /// <param name="cmdGroup">A unique identifier of the command gr oup. The pguidCmdGroup parameter can be NULL to specify the standard group.</par am>
1728 /// <param name="cmd">The command to query status for.</param>
1729 /// <param name="pCmdText">Pointer to an OLECMDTEXT structure in which to return the name and/or status information of a single command. Can be NULL to indicate that the caller does not require this information.</param>
1730 /// <param name="result">An out parameter specifying the QuerySt atusResult of the command.</param>
1731 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1732 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "p")]
1733 protected virtual int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result)
1734 {
1735 if(cmdGroup == VsMenus.guidStandardCommandSet2K)
1736 {
1737 if((VsCommands2K)cmd == VsCommands2K.SHOWALLFILE S)
1738 {
1739 result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
1740 return VSConstants.S_OK;
1741 }
1742 }
1743
1744 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1745 }
1746
1747 /// <summary>
1748 /// Disables commands when the project is in run/break mode.
1749 /// </summary>/
1750 /// <param name="commandGroup">Unique identifier of the command group</param>
1751 /// <param name="command">The command to be executed.</param>
1752 /// <returns>A QueryStatusResult describing the status of the me nu.</returns>
1753 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Main tainability", "CA1502:AvoidExcessiveComplexity"), SuppressMessage("Microsoft.Nam ing", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "InCurrent")]
1754 protected virtual bool DisableCmdInCurrentMode(Guid commandGroup , uint command)
1755 {
1756 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
1757 {
1758 return false;
1759 }
1760
1761 // Don't ask if it is not these two commandgroups.
1762 if(commandGroup == VsMenus.guidStandardCommandSet97 || c ommandGroup == VsMenus.guidStandardCommandSet2K)
1763 {
1764 if(this.ProjectMgr.IsCurrentStateASuppressComman dsMode())
1765 {
1766 if(commandGroup == VsMenus.guidStandardC ommandSet97)
1767 {
1768 switch((VsCommands)command)
1769 {
1770 default:
1771 break;
1772 case VsCommands.AddExist ingItem:
1773 case VsCommands.AddNewIt em:
1774 case VsCommands.NewFolde r:
1775 case VsCommands.Remove:
1776 case VsCommands.Cut:
1777 case VsCommands.Paste:
1778 case VsCommands.Copy:
1779 case VsCommands.EditLabe l:
1780 case VsCommands.Rename:
1781 case VsCommands.UnloadPr oject:
1782 return true;
1783 }
1784 }
1785 else if(commandGroup == VsMenus.guidStan dardCommandSet2K)
1786 {
1787 switch((VsCommands2K)command)
1788 {
1789 default:
1790 break;
1791 case VsCommands2K.EXCLUD EFROMPROJECT:
1792 case VsCommands2K.INCLUD EINPROJECT:
1793 case VsCommands2K.ADDWEB REFERENCECTX:
1794 case VsCommands2K.ADDWEB REFERENCE:
1795 case VsCommands2K.ADDREF ERENCE:
1796 case VsCommands2K.SETASS TARTPAGE:
1797 return true;
1798 }
1799 }
1800 }
1801 // If we are not in a cut or copy mode then disa ble the paste command
1802 else if(!this.ProjectMgr.AllowPasteCommand())
1803 {
1804 if(commandGroup == VsMenus.guidStandardC ommandSet97 && (VsCommands)command == VsCommands.Paste)
1805 {
1806 return true;
1807 }
1808 }
1809 }
1810
1811 return false;
1812 }
1813
1814
1815 /// <summary>
1816 /// Queries the object for the command status on a list of selec ted nodes.
1817 /// </summary>
1818 /// <param name="cmdGroup">A unique identifier of the command gr oup.</param>
1819 /// <param name="cCmds">The number of commands in the prgCmds ar ray</param>
1820 /// <param name="prgCmds">A caller-allocated array of OLECMD str uctures that indicate the commands for which the caller requires status informat ion. This method fills the cmdf member of each structure with values taken from the OLECMDF enumeration</param>
1821 /// <param name="pCmdText">Pointer to an OLECMDTEXT structure in which to return the name and/or status information of a single command. Can be NULL to indicate that the caller does not require this information. </param>
1822 /// <param name="commandOrigin">Specifies the origin of the comm and. Either it was called from the QueryStatusCommand on IVsUIHierarchy or from the IOleCommandTarget</param>
1823 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
1824 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Cmds")]
1825 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "c")]
1826 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "p")]
1827 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "prg")]
1828 protected virtual int QueryStatusSelection(Guid cmdGroup, uint c Cmds, OLECMD[] prgCmds, IntPtr pCmdText, CommandOrigin commandOrigin)
1829 {
1830 if(this.projectMgr.IsClosed)
1831 {
1832 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTE D;
1833 }
1834
1835 if(cmdGroup == Guid.Empty)
1836 {
1837 return (int)OleConstants.OLECMDERR_E_UNKNOWNGROU P;
1838 }
1839
1840 uint cmd = prgCmds[0].cmdID;
1841 QueryStatusResult queryResult = QueryStatusResult.NOTSUP PORTED;
1842
1843 // For now ask this node (that is the project node) to d isable or enable a node.
1844 // This is an optimization. Why should we ask each node for its current state? They all are in the same state.
1845 // Also please note that we return QueryStatusResult.INV ISIBLE instead of just QueryStatusResult.SUPPORTED.
1846 // The reason is that if the project has nested projects , then providing just QueryStatusResult.SUPPORTED is not enough.
1847 // What will happen is that the nested project will show grayed commands that belong to this project and does not belong to the nested p roject. (like special commands implemented by subclassed projects).
1848 // The reason is that a special command comes in that is not handled because we are in debug mode. Then VsCore asks the nested project c an you handle it.
1849 // The nested project does not know about it, thus it sh ows it on the nested project as grayed.
1850 if(this.DisableCmdInCurrentMode(cmdGroup, cmd))
1851 {
1852 queryResult = QueryStatusResult.SUPPORTED | Quer yStatusResult.INVISIBLE;
1853 }
1854 else
1855 {
1856 bool handled = false;
1857
1858 if(commandOrigin == CommandOrigin.OleCommandTarg et)
1859 {
1860 queryResult = this.QueryStatusCommandFro mOleCommandTarget(cmdGroup, cmd, out handled);
1861 }
1862
1863 if(!handled)
1864 {
1865 IList<HierarchyNode> selectedNodes = thi s.projectMgr.GetSelectedNodes();
1866
1867 // Want to disable in multiselect case.
1868 if(selectedNodes != null && selectedNode s.Count > 1)
1869 {
1870 queryResult = this.DisableComman dOnNodesThatDoNotSupportMultiSelection(cmdGroup, cmd, selectedNodes, out handled );
1871 }
1872
1873 // Now go and do the job on the nodes.
1874 if(!handled)
1875 {
1876 queryResult = this.QueryStatusSe lectionOnNodes(selectedNodes, cmdGroup, cmd, pCmdText);
1877 }
1878
1879 }
1880 }
1881
1882 // Process the results set in the QueryStatusResult
1883 if(queryResult != QueryStatusResult.NOTSUPPORTED)
1884 {
1885 // Set initial value
1886 prgCmds[0].cmdf = (uint)OLECMDF.OLECMDF_SUPPORTE D;
1887
1888 if((queryResult & QueryStatusResult.ENABLED) != 0)
1889 {
1890 prgCmds[0].cmdf |= (uint)OLECMDF.OLECMDF _ENABLED;
1891 }
1892
1893 if((queryResult & QueryStatusResult.INVISIBLE) ! = 0)
1894 {
1895 prgCmds[0].cmdf |= (uint)OLECMDF.OLECMDF _INVISIBLE;
1896 }
1897
1898 if((queryResult & QueryStatusResult.LATCHED) != 0)
1899 {
1900 prgCmds[0].cmdf |= (uint)OLECMDF.OLECMDF _LATCHED;
1901 }
1902
1903 return VSConstants.S_OK;
1904 }
1905
1906 return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED;
1907 }
1908
1909 /// <summary>
1910 /// Queries the selected nodes for the command status.
1911 /// A command is supported iff any nodes supports it.
1912 /// A command is enabled iff all nodes enable it.
1913 /// A command is invisible iff any node sets invisibility.
1914 /// A command is latched only if all are latched.
1915 /// </summary>
1916 /// <param name="selectedNodes">The list of selected nodes.</par am>
1917 /// <param name="cmdGroup">A unique identifier of the command gr oup.</param>
1918 /// <param name="cmd">The command id to query for.</param>
1919 /// <param name="pCmdText">Pointer to an OLECMDTEXT structure in which to return the name and/or status information of a single command. Can be NULL to indicate that the caller does not require this information. </param>
1920 /// <returns>Retuns the result of the query on the slected nodes .</returns>
1921 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "p")]
1922 protected virtual QueryStatusResult QueryStatusSelectionOnNodes( IList<HierarchyNode> selectedNodes, Guid cmdGroup, uint cmd, IntPtr pCmdText)
1923 {
1924 if(selectedNodes == null || selectedNodes.Count == 0)
1925 {
1926 return QueryStatusResult.NOTSUPPORTED;
1927 }
1928
1929 int result = 0;
1930 bool supported = false;
1931 bool enabled = true;
1932 bool invisible = false;
1933 bool latched = true;
1934 QueryStatusResult tempQueryResult = QueryStatusResult.NO TSUPPORTED;
1935
1936 foreach(HierarchyNode node in selectedNodes)
1937 {
1938 result = node.QueryStatusOnNode(cmdGroup, cmd, p CmdText, ref tempQueryResult);
1939 if(result < 0)
1940 {
1941 break;
1942 }
1943
1944 // cmd is supported iff any node supports cmd
1945 // cmd is enabled iff all nodes enable cmd
1946 // cmd is invisible iff any node sets invisibili ty
1947 // cmd is latched only if all are latched.
1948 supported = supported || ((tempQueryResult & Que ryStatusResult.SUPPORTED) != 0);
1949 enabled = enabled && ((tempQueryResult & QuerySt atusResult.ENABLED) != 0);
1950 invisible = invisible || ((tempQueryResult & Que ryStatusResult.INVISIBLE) != 0);
1951 latched = latched && ((tempQueryResult & QuerySt atusResult.LATCHED) != 0);
1952 }
1953
1954 QueryStatusResult queryResult = QueryStatusResult.NOTSUP PORTED;
1955
1956 if(result >= 0 && supported)
1957 {
1958 queryResult = QueryStatusResult.SUPPORTED;
1959
1960 if(enabled)
1961 {
1962 queryResult |= QueryStatusResult.ENABLED ;
1963 }
1964
1965 if(invisible)
1966 {
1967 queryResult |= QueryStatusResult.INVISIB LE;
1968 }
1969
1970 if(latched)
1971 {
1972 queryResult |= QueryStatusResult.LATCHED ;
1973 }
1974 }
1975
1976 return queryResult;
1977 }
1978
1979 #endregion
1980 protected virtual bool CanDeleteItem(__VSDELETEITEMOPERATION del eteOperation)
1981 {
1982 return this.ProjectMgr.CanProjectDeleteItems;
1983 }
1984
1985 /// <summary>
1986 /// Overwrite this method to tell that you support the default i con for this node.
1987 /// </summary>
1988 /// <returns></returns>
1989 protected virtual bool CanShowDefaultIcon()
1990 {
1991 return false;
1992 }
1993
1994 /// <summary>
1995 /// Performs save as operation for an item after the save as dia log has been processed.
1996 /// </summary>
1997 /// <param name="docData">A pointer to the rdt</param>
1998 /// <param name="newName">The newName of the item</param>
1999 /// <returns></returns>
2000 protected virtual int AfterSaveItemAs(IntPtr docData, string new Name)
2001 {
2002 throw new NotImplementedException();
2003 }
2004
2005 /// <summary>
2006 /// The method that does the cleanup.
2007 /// </summary>
2008 /// <param name="disposing">Is the Dispose called by some intern al member, or it is called by from GC.</param>
2009 protected virtual void Dispose(bool disposing)
2010 {
2011 if(this.isDisposed)
2012 {
2013 return;
2014 }
2015
2016 if(disposing)
2017 {
2018 // This will dispose any subclassed project node that implements IDisposable.
2019 if(this.oleServiceProvider != null)
2020 {
2021 // Dispose the ole service provider obje ct.
2022 this.oleServiceProvider.Dispose();
2023 }
2024 }
2025
2026 this.isDisposed = true;
2027 }
2028
2029 /// <summary>
2030 /// Sets the VSADDFILEFLAGS that will be used to call the IVsTr ackProjectDocumentsEvents2 OnAddFiles
2031 /// </summary>
2032 /// <param name="files">The files to which an array of VSADDFILE FLAGS has to be specified.</param>
2033 /// <returns></returns>
2034 protected internal virtual VSADDFILEFLAGS[] GetAddFileFlags(stri ng[] files)
2035 {
2036 if(files == null || files.Length == 0)
2037 {
2038 return new VSADDFILEFLAGS[1] { VSADDFILEFLAGS.VS ADDFILEFLAGS_NoFlags };
2039 }
2040
2041 VSADDFILEFLAGS[] addFileFlags = new VSADDFILEFLAGS[files .Length];
2042
2043 for(int i = 0; i < files.Length; i++)
2044 {
2045 addFileFlags[i] = VSADDFILEFLAGS.VSADDFILEFLAGS_ NoFlags;
2046 }
2047
2048 return addFileFlags;
2049 }
2050
2051 /// <summary>
2052 /// Sets the VSQUERYADDFILEFLAGS that will be used to call the IVsTrackProjectDocumentsEvents2 OnQueryAddFiles
2053 /// </summary>
2054 /// <param name="files">The files to which an array of VSADDFILE FLAGS has to be specified.</param>
2055 /// <returns></returns>
2056 protected internal virtual VSQUERYADDFILEFLAGS[] GetQueryAddFile Flags(string[] files)
2057 {
2058 if(files == null || files.Length == 0)
2059 {
2060 return new VSQUERYADDFILEFLAGS[1] { VSQUERYADDFI LEFLAGS.VSQUERYADDFILEFLAGS_NoFlags };
2061 }
2062
2063 VSQUERYADDFILEFLAGS[] queryAddFileFlags = new VSQUERYADD FILEFLAGS[files.Length];
2064
2065 for(int i = 0; i < files.Length; i++)
2066 {
2067 queryAddFileFlags[i] = VSQUERYADDFILEFLAGS.VSQUE RYADDFILEFLAGS_NoFlags;
2068 }
2069
2070 return queryAddFileFlags;
2071 }
2072
2073 /// <summary>
2074 /// Sets the VSREMOVEFILEFLAGS that will be used to call the IV sTrackProjectDocumentsEvents2 OnRemoveFiles
2075 /// </summary>
2076 /// <param name="files">The files to which an array of VSREMOVEF ILEFLAGS has to be specified.</param>
2077 /// <returns></returns>
2078 protected internal virtual VSREMOVEFILEFLAGS[] GetRemoveFileFlag s(string[] files)
2079 {
2080 if(files == null || files.Length == 0)
2081 {
2082 return new VSREMOVEFILEFLAGS[1] { VSREMOVEFILEFL AGS.VSREMOVEFILEFLAGS_NoFlags };
2083 }
2084
2085 VSREMOVEFILEFLAGS[] removeFileFlags = new VSREMOVEFILEFL AGS[files.Length];
2086
2087 for(int i = 0; i < files.Length; i++)
2088 {
2089 removeFileFlags[i] = VSREMOVEFILEFLAGS.VSREMOVEF ILEFLAGS_NoFlags;
2090 }
2091
2092 return removeFileFlags;
2093 }
2094
2095 /// <summary>
2096 /// Sets the VSQUERYREMOVEFILEFLAGS that will be used to call th e IVsTrackProjectDocumentsEvents2 OnQueryRemoveFiles
2097 /// </summary>
2098 /// <param name="files">The files to which an array of VSQUERYRE MOVEFILEFLAGS has to be specified.</param>
2099 /// <returns></returns>
2100 protected internal virtual VSQUERYREMOVEFILEFLAGS[] GetQueryRemo veFileFlags(string[] files)
2101 {
2102 if(files == null || files.Length == 0)
2103 {
2104 return new VSQUERYREMOVEFILEFLAGS[1] { VSQUERYRE MOVEFILEFLAGS.VSQUERYREMOVEFILEFLAGS_NoFlags };
2105 }
2106
2107 VSQUERYREMOVEFILEFLAGS[] queryRemoveFileFlags = new VSQU ERYREMOVEFILEFLAGS[files.Length];
2108
2109 for(int i = 0; i < files.Length; i++)
2110 {
2111 queryRemoveFileFlags[i] = VSQUERYREMOVEFILEFLAGS .VSQUERYREMOVEFILEFLAGS_NoFlags;
2112 }
2113
2114 return queryRemoveFileFlags;
2115 }
2116
2117 /// <summary>
2118 /// This method should be overridden to provide the list of file s and associated flags for source control.
2119 /// </summary>
2120 /// <param name="files">The list of files to be placed under sou rce control.</param>
2121 /// <param name="flags">The flags that are associated to the fil es.</param>
2122 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Scc")]
2123 protected internal virtual void GetSccFiles(IList<string> files, IList<tagVsSccFilesFlags> flags)
2124 {
2125 if(this.ExcludeNodeFromScc)
2126 {
2127 return;
2128 }
2129
2130 if(files == null)
2131 {
2132 throw new ArgumentNullException("files");
2133 }
2134
2135 if(flags == null)
2136 {
2137 throw new ArgumentNullException("flags");
2138 }
2139
2140 files.Add(this.GetMkDocument());
2141
2142 tagVsSccFilesFlags flagsToAdd = (this.firstChild != null && (this.firstChild is DependentFileNode)) ? tagVsSccFilesFlags.SFF_HasSpecialF iles : tagVsSccFilesFlags.SFF_NoFlags;
2143
2144 flags.Add(flagsToAdd);
2145 }
2146
2147 /// <summary>
2148 /// This method should be overridden to provide the list of spec ial files and associated flags for source control.
2149 /// </summary>
2150 /// <param name="sccFile">One of the file associated to the node .</param>
2151 /// <param name="files">The list of files to be placed under sou rce control.</param>
2152 /// <param name="flags">The flags that are associated to the fil es.</param>
2153 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Scc")]
2154 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "scc")]
2155 protected internal virtual void GetSccSpecialFiles(string sccFil e, IList<string> files, IList<tagVsSccFilesFlags> flags)
2156 {
2157 if(this.ExcludeNodeFromScc)
2158 {
2159 return;
2160 }
2161
2162 if(files == null)
2163 {
2164 throw new ArgumentNullException("files");
2165 }
2166
2167 if(flags == null)
2168 {
2169 throw new ArgumentNullException("flags");
2170 }
2171 }
2172
2173 /// <summary>
2174 /// Delete the item corresponding to the specified path from sto rage.
2175 /// </summary>
2176 /// <param name="path">Url of the item to delete</param>
2177 internal protected virtual void DeleteFromStorage(string path)
2178 {
2179 }
2180
2181 /// <summary>
2182 /// Determines whether a file change should be ignored or not.
2183 /// </summary>
2184 /// <param name="ignoreFlag">Flag indicating whether or not to i gnore changes (true to ignore changes).</param>
2185 protected internal virtual void IgnoreItemFileChanges(bool ignor eFlag)
2186 {
2187 }
2188
2189 /// <summary>
2190 /// Called to determine whether a project item is reloadable.
2191 /// </summary>
2192 /// <returns>True if the project item is reloadable.</returns>
2193 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Reloadable")]
2194 protected internal virtual bool IsItemReloadable()
2195 {
2196 return true;
2197 }
2198
2199 /// <summary>
2200 /// Reloads an item.
2201 /// </summary>
2202 /// <param name="reserved">Reserved parameter defined at the IVs PersistHierarchyItem2::ReloadItem parameter.</param>
2203 protected internal virtual void ReloadItem(uint reserved)
2204 {
2205
2206 }
2207
2208 /// <summary>
2209 /// Handle the Copy operation to the clipboard
2210 /// This method is typically overriden on the project node
2211 /// </summary>
2212 protected internal virtual int CopyToClipboard()
2213 {
2214 return VSConstants.E_NOTIMPL;
2215 }
2216
2217 /// <summary>
2218 /// Handle the Cut operation to the clipboard
2219 /// This method is typically overriden on the project node
2220 /// </summary>
2221 protected internal virtual int CutToClipboard()
2222 {
2223 return VSConstants.E_NOTIMPL;
2224 }
2225
2226 /// <summary>
2227 /// Handle the paste from Clipboard command.
2228 /// This method is typically overriden on the project node
2229 /// </summary>
2230 protected internal virtual int PasteFromClipboard(HierarchyNode targetNode)
2231 {
2232 return VSConstants.E_NOTIMPL;
2233 }
2234
2235 /// <summary>
2236 /// Determines if the paste command should be allowed.
2237 /// This method is typically overriden on the project node
2238 /// </summary>
2239 protected internal virtual bool AllowPasteCommand()
2240 {
2241 return false; ;
2242 }
2243
2244 /// <summary>
2245 /// Register/Unregister for Clipboard events for the UiHierarchy Window (solution explorer)
2246 /// This method is typically overriden on the project node
2247 /// </summary>
2248 /// <param name="value">true for register, false for unregister< /param>
2249 protected internal virtual void RegisterClipboardNotifications(b ool value)
2250 {
2251 return;
2252 }
2253 #endregion
2254
2255 #region public methods
2256
2257 public void OnItemAdded(HierarchyNode parent, HierarchyNode chil d)
2258 {
2259 if(null != parent.onChildAdded)
2260 {
2261 HierarchyNodeEventArgs args = new HierarchyNodeE ventArgs(child);
2262 parent.onChildAdded(parent, args);
2263 }
2264 if(parent == null)
2265 {
2266 throw new ArgumentNullException("parent");
2267 }
2268
2269 if(child == null)
2270 {
2271 throw new ArgumentNullException("child");
2272 }
2273
2274 HierarchyNode foo;
2275 foo = this.projectMgr == null ? this : this.projectMgr;
2276
2277 if(foo == this.projectMgr && (this.projectMgr.EventTrigg eringFlag & ProjectNode.EventTriggering.DoNotTriggerHierarchyEvents) != 0)
2278 {
2279 return;
2280 }
2281
2282 HierarchyNode prev = child.PreviousSibling;
2283 uint prevId = (prev != null) ? prev.hierarchyId : VSCons tants.VSITEMID_NIL;
2284 foreach(IVsHierarchyEvents sink in foo.hierarchyEventSin ks)
2285 {
2286 int result = sink.OnItemAdded(parent.hierarchyId , prevId, child.hierarchyId);
2287 if(ErrorHandler.Failed(result) && result != VSCo nstants.E_NOTIMPL)
2288 {
2289 ErrorHandler.ThrowOnFailure(result);
2290 }
2291 }
2292 }
2293
2294
2295 public void OnItemDeleted()
2296 {
2297 HierarchyNode foo;
2298 foo = this.projectMgr == null ? this : this.projectMgr;
2299
2300 if(foo == this.projectMgr && (this.projectMgr.EventTrigg eringFlag & ProjectNode.EventTriggering.DoNotTriggerHierarchyEvents) != 0)
2301 {
2302 return;
2303 }
2304
2305 if(foo.hierarchyEventSinks.Count > 0)
2306 {
2307 // Note that in some cases (deletion of project node for example), an Advise
2308 // may be removed while we are iterating over it . To get around this problem we
2309 // take a snapshot of the advise list and walk t hat.
2310 List<IVsHierarchyEvents> clonedSink = new List<I VsHierarchyEvents>();
2311
2312 foreach(IVsHierarchyEvents anEvent in foo.hierar chyEventSinks)
2313 {
2314 clonedSink.Add(anEvent);
2315 }
2316
2317 foreach(IVsHierarchyEvents clonedEvent in cloned Sink)
2318 {
2319 int result = clonedEvent.OnItemDeleted(t his.hierarchyId);
2320 if(ErrorHandler.Failed(result) && result != VSConstants.E_NOTIMPL)
2321 {
2322 ErrorHandler.ThrowOnFailure(resu lt);
2323 }
2324 }
2325 }
2326 }
2327
2328 public void OnItemsAppended(HierarchyNode parent)
2329 {
2330 if(parent == null)
2331 {
2332 throw new ArgumentNullException("parent");
2333 }
2334
2335 HierarchyNode foo;
2336 foo = this.projectMgr == null ? this : this.projectMgr;
2337
2338 if(foo == this.projectMgr && (this.projectMgr.EventTrigg eringFlag & ProjectNode.EventTriggering.DoNotTriggerHierarchyEvents) != 0)
2339 {
2340 return;
2341 }
2342
2343 foreach(IVsHierarchyEvents sink in foo.hierarchyEventSin ks)
2344 {
2345 int result = sink.OnItemsAppended(parent.hierarc hyId);
2346
2347 if(ErrorHandler.Failed(result) && result != VSCo nstants.E_NOTIMPL)
2348 {
2349 ErrorHandler.ThrowOnFailure(result);
2350 }
2351 }
2352 }
2353
2354
2355 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "propid")]
2356 public void OnPropertyChanged(HierarchyNode node, int propid, ui nt flags)
2357 {
2358 if(node == null)
2359 {
2360 throw new ArgumentNullException("node");
2361 }
2362 HierarchyNode foo;
2363 foo = this.projectMgr == null ? this : this.projectMgr;
2364 if(foo == this.projectMgr && (this.projectMgr.EventTrigg eringFlag & ProjectNode.EventTriggering.DoNotTriggerHierarchyEvents) != 0)
2365 {
2366 return;
2367 }
2368
2369 foreach(IVsHierarchyEvents sink in foo.hierarchyEventSin ks)
2370 {
2371 int result = sink.OnPropertyChanged(node.hierarc hyId, propid, flags);
2372
2373 if(ErrorHandler.Failed(result) && result != VSCo nstants.E_NOTIMPL)
2374 {
2375 ErrorHandler.ThrowOnFailure(result);
2376 }
2377 }
2378 }
2379
2380
2381 public void OnInvalidateItems(HierarchyNode parent)
2382 {
2383 if(parent == null)
2384 {
2385 throw new ArgumentNullException("parent");
2386 }
2387 HierarchyNode foo;
2388 foo = this.projectMgr == null ? this : this.projectMgr;
2389 if(foo == this.projectMgr && (this.projectMgr.EventTrigg eringFlag & ProjectNode.EventTriggering.DoNotTriggerHierarchyEvents) != 0)
2390 {
2391 return;
2392 }
2393
2394 foreach(IVsHierarchyEvents sink in foo.hierarchyEventSin ks)
2395 {
2396 int result = sink.OnInvalidateItems(parent.hiera rchyId);
2397
2398 if(ErrorHandler.Failed(result) && result != VSCo nstants.E_NOTIMPL)
2399 {
2400 ErrorHandler.ThrowOnFailure(result);
2401 }
2402 }
2403 }
2404
2405 /// <summary>
2406 /// Causes the hierarchy to be redrawn.
2407 /// </summary>
2408 /// <param name="element">Used by the hierarchy to decide which element to redraw</param>
2409 [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBe CasedCorrectly", MessageId = "Re")]
2410 [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShould BeCasedCorrectly", MessageId = "ReDraw")]
2411 public virtual void ReDraw(UIHierarchyElement element)
2412 {
2413
2414 foreach(IVsHierarchyEvents sink in this.projectMgr.hiera rchyEventSinks)
2415 {
2416 int result;
2417 if((element & UIHierarchyElement.Icon) != 0)
2418 {
2419 result = sink.OnPropertyChanged(this.ID, (int)__VSHPROPID.VSHPROPID_IconIndex, 0);
2420 Debug.Assert(ErrorHandler.Succeeded(resu lt), "Redraw failed for node " + this.GetMkDocument());
2421 }
2422
2423 if((element & UIHierarchyElement.Caption) != 0)
2424 {
2425 result = sink.OnPropertyChanged(this.ID, (int)__VSHPROPID.VSHPROPID_Caption, 0);
2426 Debug.Assert(ErrorHandler.Succeeded(resu lt), "Redraw failed for node " + this.GetMkDocument());
2427 }
2428
2429 if((element & UIHierarchyElement.SccState) != 0)
2430 {
2431 result = sink.OnPropertyChanged(this.ID, (int)__VSHPROPID.VSHPROPID_StateIconIndex, 0);
2432 Debug.Assert(ErrorHandler.Succeeded(resu lt), "Redraw failed for node " + this.GetMkDocument());
2433 }
2434 }
2435
2436 }
2437
2438 /// <summary>
2439 /// Finds a non virtual hierarchy item by its project element.
2440 /// </summary>
2441 /// <param name="node">The Project element to find</param>
2442 /// <returns>The node found</returns>
2443 public HierarchyNode FindChildByProjectElement(ProjectElement no de)
2444 {
2445 if(node == null)
2446 {
2447 throw new ArgumentNullException("node");
2448 }
2449
2450 for(HierarchyNode child = this.FirstChild; child != null ; child = child.NextSibling)
2451 {
2452 if(!child.ItemNode.IsVirtual && child.ItemNode = = node)
2453 {
2454 return child;
2455 }
2456 }
2457 return null;
2458 }
2459
2460 public object GetService(Type type)
2461 {
2462 if(type == null)
2463 {
2464 throw new ArgumentNullException("type");
2465 }
2466
2467 if(this.projectMgr.Site == null) return null;
2468 return this.projectMgr.Site.GetService(type);
2469 }
2470
2471
2472 #endregion
2473
2474 #region IDisposable
2475 /// <summary>
2476 /// The IDispose interface Dispose method for disposing the obje ct determinastically.
2477 /// </summary>
2478 public void Dispose()
2479 {
2480 this.Dispose(true);
2481 GC.SuppressFinalize(this);
2482 }
2483
2484 #endregion
2485
2486 #region IVsHierarchy methods
2487
2488 public virtual int AdviseHierarchyEvents(IVsHierarchyEvents sink , out uint cookie)
2489 {
2490 cookie = this.hierarchyEventSinks.Add(sink) + 1;
2491 return VSConstants.S_OK;
2492 }
2493
2494
2495 public virtual int Close()
2496 {
2497 DocumentManager manager = this.GetDocumentManager();
2498 try
2499 {
2500 if(manager != null)
2501 {
2502 manager.Close(__FRAMECLOSE.FRAMECLOSE_Pr omptSave);
2503 }
2504
2505 }
2506 catch { }
2507 finally
2508 {
2509 this.Dispose(true);
2510 }
2511
2512 return VSConstants.S_OK;
2513 }
2514
2515
2516 public virtual int GetCanonicalName(uint itemId, out string name )
2517 {
2518 HierarchyNode n = this.projectMgr.NodeFromItemId(itemId) ;
2519 name = (n != null) ? n.GetCanonicalName() : null;
2520 return VSConstants.S_OK;
2521 }
2522
2523
2524 public virtual int GetGuidProperty(uint itemId, int propid, out Guid guid)
2525 {
2526 guid = Guid.Empty;
2527 HierarchyNode n = this.projectMgr.NodeFromItemId(itemId) ;
2528 if(n != null)
2529 {
2530 int hr = n.GetGuidProperty(propid, out guid);
2531 __VSHPROPID vspropId = (__VSHPROPID)propid;
2532 CCITracing.TraceCall(vspropId.ToString() + "=" + guid.ToString());
2533 return hr;
2534 }
2535 if(guid == Guid.Empty)
2536 {
2537 return VSConstants.DISP_E_MEMBERNOTFOUND;
2538 }
2539 return VSConstants.S_OK;
2540 }
2541
2542
2543 public virtual int GetProperty(uint itemId, int propId, out obje ct propVal)
2544 {
2545 propVal = null;
2546 if(itemId != VSConstants.VSITEMID_ROOT && propId == (int )__VSHPROPID.VSHPROPID_IconImgList)
2547 {
2548 return VSConstants.DISP_E_MEMBERNOTFOUND;
2549 }
2550
2551
2552 HierarchyNode n = this.projectMgr.NodeFromItemId(itemId) ;
2553 if(n != null)
2554 {
2555 propVal = n.GetProperty(propId);
2556 }
2557 if(propVal == null)
2558 {
2559 return VSConstants.DISP_E_MEMBERNOTFOUND;
2560 }
2561 return VSConstants.S_OK;
2562 }
2563
2564
2565 public virtual int GetNestedHierarchy(uint itemId, ref Guid iidH ierarchyNested, out IntPtr ppHierarchyNested, out uint pItemId)
2566 {
2567 ppHierarchyNested = IntPtr.Zero;
2568 pItemId = 0;
2569 // If itemid is not a nested hierarchy we must return E_ FAIL.
2570 return VSConstants.E_FAIL;
2571 }
2572
2573
2574 public virtual int GetSite(out Microsoft.VisualStudio.OLE.Intero p.IServiceProvider site)
2575 {
2576 site = this.projectMgr.Site.GetService(typeof(Microsoft. VisualStudio.OLE.Interop.IServiceProvider)) as Microsoft.VisualStudio.OLE.Intero p.IServiceProvider;
2577 return VSConstants.S_OK;
2578 }
2579
2580
2581 /// <summary>
2582 /// the canonicalName of an item is it's URL, or better phrased,
2583 /// the persistence data we put into @RelPath, which is a relati ve URL
2584 /// to the root project
2585 /// returning the itemID from this means scanning the list
2586 /// </summary>
2587 /// <param name="name"></param>
2588 /// <param name="itemId"></param>
2589 public virtual int ParseCanonicalName(string name, out uint item Id)
2590 {
2591 // we always start at the current node and go it's child ren down, so
2592 // if you want to scan the whole tree, better call
2593 // the root
2594 itemId = 0;
2595
2596 // The default implemenation will check for case insensi tive comparision.
2597 if(String.Compare(name, this.Url, StringComparison.Ordin alIgnoreCase) == 0)
2598 {
2599 itemId = this.hierarchyId;
2600 return VSConstants.S_OK;
2601 }
2602 if(itemId == 0 && this.firstChild != null)
2603 {
2604 ErrorHandler.ThrowOnFailure(this.firstChild.Pars eCanonicalName(name, out itemId));
2605 }
2606 if(itemId == 0 && this.nextSibling != null)
2607 {
2608 ErrorHandler.ThrowOnFailure(this.nextSibling.Par seCanonicalName(name, out itemId));
2609 }
2610 return VSConstants.S_OK;
2611 }
2612
2613
2614 public virtual int QueryClose(out int fCanClose)
2615 {
2616 fCanClose = 1;
2617 return VSConstants.S_OK;
2618 }
2619
2620
2621 public virtual int SetGuidProperty(uint itemId, int propid, ref Guid guid)
2622 {
2623 HierarchyNode n = this.projectMgr.NodeFromItemId(itemId) ;
2624 int rc = VSConstants.E_INVALIDARG;
2625 if(n != null)
2626 {
2627 rc = n.SetGuidProperty(propid, ref guid);
2628 }
2629 return rc;
2630 }
2631
2632
2633 public virtual int SetProperty(uint itemId, int propid, object v alue)
2634 {
2635 HierarchyNode n = this.projectMgr.NodeFromItemId(itemId) ;
2636 if(n != null)
2637 {
2638 return n.SetProperty(propid, value);
2639 }
2640 else
2641 {
2642 return VSConstants.DISP_E_MEMBERNOTFOUND;
2643 }
2644 }
2645
2646
2647 public virtual int SetSite(Microsoft.VisualStudio.OLE.Interop.IS erviceProvider site)
2648 {
2649 return VSConstants.E_NOTIMPL;
2650 }
2651
2652
2653 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usag e", "CA2233:OperationsShouldNotOverflow", MessageId = "cookie-1")]
2654 public virtual int UnadviseHierarchyEvents(uint cookie)
2655 {
2656 this.hierarchyEventSinks.RemoveAt(cookie - 1);
2657 return VSConstants.S_OK;
2658 }
2659
2660
2661 public int Unused0()
2662 {
2663 return VSConstants.E_NOTIMPL;
2664 }
2665
2666
2667 public int Unused1()
2668 {
2669 return VSConstants.E_NOTIMPL;
2670 }
2671
2672
2673 public int Unused2()
2674 {
2675 return VSConstants.E_NOTIMPL;
2676 }
2677
2678
2679 public int Unused3()
2680 {
2681 return VSConstants.E_NOTIMPL;
2682 }
2683
2684
2685 public int Unused4()
2686 {
2687 return VSConstants.E_NOTIMPL;
2688 }
2689 #endregion
2690
2691 #region IVsUIHierarchy methods
2692
2693 public virtual int ExecCommand(uint itemId, ref Guid guidCmdGrou p, uint nCmdId, uint nCmdExecOpt, IntPtr pvain, IntPtr p)
2694 {
2695 return this.InternalExecCommand(guidCmdGroup, nCmdId, nC mdExecOpt, pvain, p, CommandOrigin.UiHierarchy);
2696 }
2697
2698 public virtual int QueryStatusCommand(uint itemId, ref Guid guid CmdGroup, uint cCmds, OLECMD[] cmds, IntPtr pCmdText)
2699 {
2700 return this.QueryStatusSelection(guidCmdGroup, cCmds, cm ds, pCmdText, CommandOrigin.UiHierarchy);
2701 }
2702 #endregion
2703
2704 #region IVsPersistHierarchyItem2 methods
2705
2706 /// <summary>
2707 /// Determines whether the hierarchy item changed.
2708 /// </summary>
2709 /// <param name="itemId">Item identifier of the hierarchy item c ontained in VSITEMID.</param>
2710 /// <param name="docData">Pointer to the IUnknown interface of t he hierarchy item.</param>
2711 /// <param name="isDirty">true if the hierarchy item changed.</p aram>
2712 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code. </returns>
2713 public virtual int IsItemDirty(uint itemId, IntPtr docData, out int isDirty)
2714 {
2715 IVsPersistDocData pd = (IVsPersistDocData)Marshal.GetObj ectForIUnknown(docData);
2716 return ErrorHandler.ThrowOnFailure(pd.IsDocDataDirty(out isDirty));
2717 }
2718
2719 /// <summary>
2720 /// Saves the hierarchy item to disk.
2721 /// </summary>
2722 /// <param name="saveFlag">Flags whose values are taken from the VSSAVEFLAGS enumeration.</param>
2723 /// <param name="silentSaveAsName">New filename when doing silen t save as</param>
2724 /// <param name="itemid">Item identifier of the hierarchy item s aved from VSITEMID.</param>
2725 /// <param name="docData">Item identifier of the hierarchy item saved from VSITEMID.</param>
2726 /// <param name="cancelled">[out] true if the save action was ca nceled.</param>
2727 /// <returns>[out] true if the save action was canceled.</return s>
2728 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Main tainability", "CA1502:AvoidExcessiveComplexity")]
2729 public virtual int SaveItem(VSSAVEFLAGS saveFlag, string silentS aveAsName, uint itemid, IntPtr docData, out int cancelled)
2730 {
2731 cancelled = 0;
2732
2733 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
2734 {
2735 return VSConstants.E_FAIL;
2736 }
2737
2738 // Validate itemid
2739 if(itemid == VSConstants.VSITEMID_ROOT || itemid == VSCo nstants.VSITEMID_SELECTION)
2740 {
2741 return VSConstants.E_INVALIDARG;
2742 }
2743
2744 HierarchyNode node = this.ProjectMgr.NodeFromItemId(item id);
2745 if(node == null)
2746 {
2747 return VSConstants.E_FAIL;
2748 }
2749
2750 string existingFileMoniker = node.GetMkDocument();
2751
2752 // We can only perform save if the document is open
2753 if(docData == IntPtr.Zero)
2754 {
2755 string errorMessage = string.Format(CultureInfo. CurrentCulture, SR.GetString(SR.CanNotSaveFileNotOpeneInEditor, CultureInfo.Curr entUICulture), node.Url);
2756 throw new InvalidOperationException(errorMessage );
2757 }
2758
2759 string docNew = String.Empty;
2760 int returnCode = VSConstants.S_OK;
2761 IPersistFileFormat ff = null;
2762 IVsPersistDocData dd = null;
2763 IVsUIShell shell = this.projectMgr.Site.GetService(typeo f(SVsUIShell)) as IVsUIShell;
2764
2765 if(shell == null)
2766 {
2767 return VSConstants.E_FAIL;
2768 }
2769
2770 try
2771 {
2772 //Save docdata object.
2773 //For the saveas action a dialog is show in orde r to enter new location of file.
2774 //In case of a save action and the file is reado nly a dialog is also shown
2775 //with a couple of options, SaveAs, Overwrite or Cancel.
2776 ff = Marshal.GetObjectForIUnknown(docData) as IP ersistFileFormat;
2777 if(ff == null)
2778 {
2779 return VSConstants.E_FAIL;
2780 }
2781 if(VSSAVEFLAGS.VSSAVE_SilentSave == saveFlag)
2782 {
2783 ErrorHandler.ThrowOnFailure(shell.SaveDo cDataToFile(saveFlag, ff, silentSaveAsName, out docNew, out cancelled));
2784 }
2785 else
2786 {
2787 dd = Marshal.GetObjectForIUnknown(docDat a) as IVsPersistDocData;
2788 if(dd == null)
2789 {
2790 return VSConstants.E_FAIL;
2791 }
2792 ErrorHandler.ThrowOnFailure(dd.SaveDocDa ta(saveFlag, out docNew, out cancelled));
2793 }
2794
2795 // We can be unloaded after the SaveDocData() ca ll if the save caused a designer to add a file and this caused
2796 // the project file to be reloaded (QEQS caused a newer version of the project file to be downloaded). So we check
2797 // here.
2798 if(this.ProjectMgr == null || this.ProjectMgr.Is Closed)
2799 {
2800 cancelled = 1;
2801 return (int)OleConstants.OLECMDERR_E_CAN CELED;
2802 }
2803 else
2804 {
2805 // if a SaveAs occurred we need to updat e to the fact our item's name has changed.
2806 // this includes the following:
2807 // 1. call RenameDocument on the RunningDocumentTable
2808 // 2. update the full path name f or the item in our hierarchy
2809 // 3. a directory-based project m ay need to transfer the open editor to the
2810 // MiscFiles project if th e new file is saved outside of the project directory.
2811 // This is accomplished by calling IVsExternalFilesManager::TransferDocument
2812
2813 // we have three options for a saveas ac tion to be performed
2814 // 1. the flag was set (the save as comm and was triggered)
2815 // 2. a silent save specifying a new doc ument name
2816 // 3. a save command was triggered but w as not possible because the file has a read only attrib. Therefore
2817 // the user has chosen to do a save a s in the dialog that showed up
2818 bool emptyOrSamePath = String.IsNullOrEm pty(docNew) || NativeMethods.IsSamePath(existingFileMoniker, docNew);
2819 bool saveAs = ((saveFlag == VSSAVEFLAGS. VSSAVE_SaveAs)) ||
2820 ((saveFlag == VSSAVEFLAGS.VSSAVE _SilentSave) && !emptyOrSamePath) ||
2821 ((saveFlag == VSSAVEFLAGS.VSSAVE _Save) && !emptyOrSamePath);
2822
2823 if(saveAs)
2824 {
2825 returnCode = node.AfterSaveItemA s(docData, docNew);
2826
2827 // If it has been cancelled reco ver the old name.
2828 if((returnCode == (int)OleConsta nts.OLECMDERR_E_CANCELED || returnCode == VSConstants.E_ABORT))
2829 {
2830 // Cleanup.
2831 this.DeleteFromStorage(d ocNew);
2832 if(this is ProjectNode & & File.Exists(docNew))
2833 {
2834 File.Delete(docN ew);
2835 }
2836
2837 if(ff != null)
2838 {
2839 returnCode = she ll.SaveDocDataToFile(VSSAVEFLAGS.VSSAVE_SilentSave, ff, existingFileMoniker, out docNew, out cancelled);
2840 }
2841 }
2842 else if(returnCode != VSConstant s.S_OK)
2843 {
2844 ErrorHandler.ThrowOnFail ure(returnCode);
2845 }
2846 }
2847 }
2848 }
2849 catch(COMException e)
2850 {
2851 Trace.WriteLine("Exception :" + e.Message);
2852 returnCode = e.ErrorCode;
2853
2854 // Try to recover
2855 if(ff != null)
2856 {
2857 ErrorHandler.ThrowOnFailure(shell.SaveDo cDataToFile(VSSAVEFLAGS.VSSAVE_SilentSave, ff, existingFileMoniker, out docNew, out cancelled));
2858 }
2859 }
2860
2861 return returnCode;
2862 }
2863
2864 /// <summary>
2865 /// Flag indicating that changes to a file can be ignored when i tem is saved or reloaded.
2866 /// </summary>
2867 /// <param name="itemId">Specifies the item id from VSITEMID.</p aram>
2868 /// <param name="ignoreFlag">Flag indicating whether or not to i gnore changes (1 to ignore, 0 to stop ignoring).</param>
2869 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code.</returns>
2870 public virtual int IgnoreItemFileChanges(uint itemId, int ignore Flag)
2871 {
2872 #region precondition
2873 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
2874 {
2875 return VSConstants.E_FAIL;
2876 }
2877 #endregion
2878
2879 HierarchyNode n = this.ProjectMgr.NodeFromItemId(itemId) ;
2880 if(n != null)
2881 {
2882 n.IgnoreItemFileChanges(ignoreFlag == 0 ? false : true);
2883 }
2884
2885 return VSConstants.S_OK;
2886 }
2887
2888 /// <summary>
2889 /// Called to determine whether a project item is reloadable bef ore calling ReloadItem.
2890 /// </summary>
2891 /// <param name="itemId">Item identifier of an item in the hiera rchy. Valid values are VSITEMID_NIL, VSITEMID_ROOT and VSITEMID_SELECTION.</para m>
2892 /// <param name="isReloadable">A flag indicating that the projec t item is reloadable (1 for reloadable, 0 for non-reloadable).</param>
2893 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code. </returns>
2894 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBe SpelledCorrectly", MessageId = "Reloadable")]
2895 public virtual int IsItemReloadable(uint itemId, out int isReloa dable)
2896 {
2897 isReloadable = 0;
2898
2899 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
2900 {
2901 return VSConstants.E_FAIL;
2902 }
2903
2904 HierarchyNode n = this.ProjectMgr.NodeFromItemId(itemId) ;
2905 if(n != null)
2906 {
2907 isReloadable = (n.IsItemReloadable()) ? 1 : 0;
2908 }
2909
2910 return VSConstants.S_OK;
2911 }
2912
2913 /// <summary>
2914 /// Called to reload a project item.
2915 /// </summary>
2916 /// <param name="itemId">Specifies itemid from VSITEMID.</param>
2917 /// <param name="reserved">Reserved.</param>
2918 /// <returns>If the method succeeds, it returns S_OK. If it fail s, it returns an error code. </returns>
2919 public virtual int ReloadItem(uint itemId, uint reserved)
2920 {
2921 #region precondition
2922 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
2923 {
2924 return VSConstants.E_FAIL;
2925 }
2926 #endregion
2927
2928 HierarchyNode n = this.ProjectMgr.NodeFromItemId(itemId) ;
2929 if(n != null)
2930 {
2931 n.ReloadItem(reserved);
2932 }
2933
2934 return VSConstants.S_OK;
2935 }
2936 #endregion
2937
2938 #region IOleCommandTarget methods
2939 /// <summary>
2940 /// CommandTarget.Exec is called for most major operations if th ey are NOT UI based. Otherwise IVSUInode::exec is called first
2941 /// </summary>
2942 public virtual int Exec(ref Guid guidCmdGroup, uint nCmdId, uint nCmdExecOpt, IntPtr pvaIn, IntPtr pvaOut)
2943 {
2944 return this.InternalExecCommand(guidCmdGroup, nCmdId, nC mdExecOpt, pvaIn, pvaOut, CommandOrigin.OleCommandTarget);
2945 }
2946
2947 /// <summary>
2948 /// Queries the object for the command status
2949 /// </summary>
2950 /// <remarks>we only support one command at a time, i.e. the fir st member in the OLECMD array</remarks>
2951 public virtual int QueryStatus(ref Guid guidCmdGroup, uint cCmds , OLECMD[] prgCmds, IntPtr pCmdText)
2952 {
2953 return this.QueryStatusSelection(guidCmdGroup, cCmds, pr gCmds, pCmdText, CommandOrigin.OleCommandTarget);
2954 }
2955 #endregion
2956
2957 #region IVsHierarchyDeleteHandler methods
2958
2959 public virtual int DeleteItem(uint delItemOp, uint itemId)
2960 {
2961 if(itemId == VSConstants.VSITEMID_SELECTION)
2962 {
2963 return VSConstants.E_INVALIDARG;
2964 }
2965
2966 HierarchyNode node = this.projectMgr.NodeFromItemId(item Id);
2967 if(node != null)
2968 {
2969 node.Remove((delItemOp & (uint)__VSDELETEITEMOPE RATION.DELITEMOP_DeleteFromStorage) != 0);
2970 return VSConstants.S_OK;
2971 }
2972
2973 return VSConstants.E_FAIL;
2974 }
2975
2976
2977 public virtual int QueryDeleteItem(uint delItemOp, uint itemId, out int candelete)
2978 {
2979 candelete = 0;
2980 if(itemId == VSConstants.VSITEMID_SELECTION)
2981 {
2982 return VSConstants.E_INVALIDARG;
2983 }
2984
2985 if(this.ProjectMgr == null || this.ProjectMgr.IsClosed)
2986 {
2987 return VSConstants.E_FAIL;
2988 }
2989
2990 // We ask the project what state it is. If he is a state that should not allow delete then we return.
2991 if(this.ProjectMgr.IsCurrentStateASuppressCommandsMode() )
2992 {
2993 return VSConstants.S_OK;
2994 }
2995
2996 HierarchyNode node = this.projectMgr.NodeFromItemId(item Id);
2997
2998 if(node == null)
2999 {
3000 return VSConstants.E_FAIL;
3001 }
3002
3003 // Ask the nodes if they can remove the item.
3004 bool canDeleteItem = node.CanDeleteItem((__VSDELETEITEMO PERATION)delItemOp);
3005 if(canDeleteItem)
3006 {
3007 candelete = 1;
3008 }
3009
3010 return VSConstants.S_OK;
3011 }
3012 #endregion
3013
3014 #region IVsHierarchyDropDataSource2 methods
3015
3016 public virtual int GetDropInfo(out uint pdwOKEffects, out Micros oft.VisualStudio.OLE.Interop.IDataObject ppDataObject, out IDropSource ppDropSou rce)
3017 {
3018 pdwOKEffects = (uint)DropEffect.None;
3019 ppDataObject = null;
3020 ppDropSource = null;
3021 return VSConstants.E_NOTIMPL;
3022 }
3023
3024 public virtual int OnDropNotify(int fDropped, uint dwEffects)
3025 {
3026 return VSConstants.E_NOTIMPL;
3027 }
3028
3029 public virtual int OnBeforeDropNotify(Microsoft.VisualStudio.OLE .Interop.IDataObject pDataObject, uint dwEffect, out int fCancelDrop)
3030 {
3031 pDataObject = null;
3032 fCancelDrop = 0;
3033 return VSConstants.E_NOTIMPL;
3034 }
3035 #endregion
3036
3037 #region IVsHierarchyDropDataTarget methods
3038
3039 public virtual int DragEnter(Microsoft.VisualStudio.OLE.Interop. IDataObject pDataObject, uint grfKeyState, uint itemid, ref uint pdwEffect)
3040 {
3041 return VSConstants.E_NOTIMPL;
3042 }
3043
3044 public virtual int DragLeave()
3045 {
3046 return VSConstants.E_NOTIMPL;
3047 }
3048
3049 public virtual int DragOver(uint grfKeyState, uint itemid, ref u int pdwEffect)
3050 {
3051 return VSConstants.E_NOTIMPL;
3052 }
3053
3054 public virtual int Drop(Microsoft.VisualStudio.OLE.Interop.IData Object pDataObject, uint grfKeyState, uint itemid, ref uint pdwEffect)
3055 {
3056 return VSConstants.E_NOTIMPL;
3057 }
3058 #endregion
3059
3060 #region helper methods
3061 internal HierarchyNode FindChild(string name)
3062 {
3063 if(String.IsNullOrEmpty(name))
3064 {
3065 return null;
3066 }
3067
3068 HierarchyNode result;
3069 for(HierarchyNode child = this.firstChild; child != null ; child = child.NextSibling)
3070 {
3071 if(!String.IsNullOrEmpty(child.VirtualNodeName) && String.Compare(child.VirtualNodeName, name, StringComparison.OrdinalIgnoreCas e) == 0)
3072 {
3073 return child;
3074 }
3075 // If it is a foldernode then it has a virtual n ame but we want to find folder nodes by the document moniker or url
3076 else if((String.IsNullOrEmpty(child.VirtualNodeN ame) || (child is FolderNode)) &&
3077 (NativeMethods.IsSamePath(child. GetMkDocument(), name) || NativeMethods.IsSamePath(child.Url, name)))
3078 {
3079 return child;
3080 }
3081
3082 result = child.FindChild(name);
3083 if(result != null)
3084 {
3085 return result;
3086 }
3087 }
3088 return null;
3089 }
3090
3091 /// <summary>
3092 /// Recursively find all nodes of type T
3093 /// </summary>
3094 /// <typeparam name="T">The type of hierachy node being serched for</typeparam>
3095 /// <param name="nodes">A list of nodes of type T</param>
3096 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Perf ormance", "CA1811:AvoidUncalledPrivateCode")]
3097 internal void FindNodesOfType<T>(List<T> nodes)
3098 where T : HierarchyNode
3099 {
3100 for(HierarchyNode n = this.FirstChild; n != null; n = n. NextSibling)
3101 {
3102 if(n is T)
3103 {
3104 T nodeAsT = (T)n;
3105 nodes.Add(nodeAsT);
3106 }
3107
3108 n.FindNodesOfType<T>(nodes);
3109 }
3110 }
3111
3112 /// <summary>
3113 /// Adds an item from a project refererence to target node.
3114 /// </summary>
3115 /// <param name="projectRef"></param>
3116 /// <param name="targetNode"></param>
3117 internal bool AddFileToNodeFromProjectReference(string projectRe f, HierarchyNode targetNode)
3118 {
3119 if(String.IsNullOrEmpty(projectRef))
3120 {
3121 throw new ArgumentException(SR.GetString(SR.Para meterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "projectRef");
3122 }
3123
3124 if(targetNode == null)
3125 {
3126 throw new ArgumentNullException("targetNode");
3127 }
3128
3129 IVsSolution solution = this.GetService(typeof(IVsSolutio n)) as IVsSolution;
3130 if(solution == null)
3131 {
3132 throw new InvalidOperationException();
3133 }
3134
3135 uint itemidLoc;
3136 IVsHierarchy hierarchy;
3137 string str;
3138 VSUPDATEPROJREFREASON[] reason = new VSUPDATEPROJREFREAS ON[1];
3139 ErrorHandler.ThrowOnFailure(solution.GetItemOfProjref(pr ojectRef, out hierarchy, out itemidLoc, out str, reason));
3140 if(hierarchy == null)
3141 {
3142 throw new InvalidOperationException();
3143 }
3144
3145 // This will throw invalid cast exception if the hierrac hy is not a project.
3146 IVsProject project = (IVsProject)hierarchy;
3147
3148 string moniker;
3149 ErrorHandler.ThrowOnFailure(project.GetMkDocument(itemid Loc, out moniker));
3150 string[] files = new String[1] { moniker };
3151 VSADDRESULT[] vsaddresult = new VSADDRESULT[1];
3152 vsaddresult[0] = VSADDRESULT.ADDRESULT_Failure;
3153 int addResult = targetNode.ProjectMgr.AddItem(targetNode .ID, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, null, 0, files, IntPtr.Zero, vsadd result);
3154 if(addResult != VSConstants.S_OK && addResult != VSConst ants.S_FALSE && addResult != (int)OleConstants.OLECMDERR_E_CANCELED)
3155 {
3156 ErrorHandler.ThrowOnFailure(addResult);
3157 return false;
3158 }
3159 return (vsaddresult[0] == VSADDRESULT.ADDRESULT_Success) ;
3160 }
3161
3162 internal void InstantiateItemsDraggedOrCutOrCopiedList()
3163 {
3164 this.itemsDraggedOrCutOrCopied = new List<HierarchyNode> ();
3165 }
3166 #endregion
3167 }
3168 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698