private static bool IsNodeNonMemberItem(HierarchyNode node, object criteria) { bool isNonMemberItem = false; if (node != null) { object propObj = node.GetProperty((int) __VSHPROPID.VSHPROPID_IsNonMemberItem); if (propObj != null) { Boolean.TryParse(propObj.ToString(), out isNonMemberItem); } } return isNonMemberItem; }
/// <summary> /// Process dataobject from Drag/Drop/Cut/Copy/Paste operation /// </summary> /// <remarks>The targetNode is set if the method is called from a drop operation, otherwise it is null</remarks> internal DropDataType ProcessSelectionDataObject(IOleDataObject dataObject, HierarchyNode targetNode) { DropDataType dropDataType = DropDataType.None; bool isWindowsFormat = false; // Try to get it as a directory based project. List<string> filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSSTGPROJECTITEMS, dataObject, out dropDataType); if (filesDropped.Count == 0) { filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSREFPROJECTITEMS, dataObject, out dropDataType); } if (filesDropped.Count == 0) { filesDropped = DragDropHelper.GetDroppedFiles(NativeMethods.CF_HDROP, dataObject, out dropDataType); isWindowsFormat = (filesDropped.Count > 0); } if (dropDataType != DropDataType.None && filesDropped.Count > 0) { string[] filesDroppedAsArray = filesDropped.ToArray(); HierarchyNode node = (targetNode == null) ? this : targetNode; // For directory based projects the content of the clipboard is a double-NULL terminated list of Projref strings. if (isWindowsFormat) { // This is the code path when source is windows explorer VSADDRESULT[] vsaddresults = new VSADDRESULT[1]; vsaddresults[0] = VSADDRESULT.ADDRESULT_Failure; int addResult = AddItem(node.ID, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, null, (uint)filesDropped.Count, filesDroppedAsArray, IntPtr.Zero, vsaddresults); if (addResult != VSConstants.S_OK && addResult != VSConstants.S_FALSE && addResult != (int)OleConstants.OLECMDERR_E_CANCELED && vsaddresults[0] != VSADDRESULT.ADDRESULT_Success) { ErrorHandler.ThrowOnFailure(addResult); } return dropDataType; } else { if (AddFilesFromProjectReferences(node, filesDroppedAsArray)) { return dropDataType; } } } // If we reached this point then the drop data must be set to None. // Otherwise the OnPaste will be called with a valid DropData and that would actually delete the item. return DropDataType.None; }
public NodeProperties(HierarchyNode node) { if (node == null) { throw new ArgumentNullException("node"); } this.node = node; }
public FolderNodeProperties(HierarchyNode node) : base(node) { }
public SingleFileGeneratorNodeProperties(HierarchyNode node) : base(node) { }
/// <summary> /// Process dataobject from Drag/Drop/Cut/Copy/Paste operation /// </summary> /// <remarks>The targetNode is set if the method is called from a drop operation, otherwise it is null</remarks> internal DropDataType ProcessSelectionDataObject(IOleDataObject dataObject, HierarchyNode targetNode, uint grfKeyState) { DropDataType dropDataType = DropDataType.None; bool isWindowsFormat = false; // Try to get it as a directory based project. List<string> filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSSTGPROJECTITEMS, dataObject, out dropDataType); if (filesDropped.Count == 0) { filesDropped = DragDropHelper.GetDroppedFiles(DragDropHelper.CF_VSREFPROJECTITEMS, dataObject, out dropDataType); } if (filesDropped.Count == 0) { filesDropped = DragDropHelper.GetDroppedFiles(NativeMethods.CF_HDROP, dataObject, out dropDataType); isWindowsFormat = (filesDropped.Count > 0); } dropItems.Clear(); if (dropDataType != DropDataType.None && filesDropped.Count > 0) { bool saveAllowDuplicateLinks = this.AllowDuplicateLinks; try { DropEffect dropEffect = this.QueryDropEffect(dropDataType, grfKeyState); this.dropAsCopy = dropEffect == DropEffect.Copy; if (dropEffect == DropEffect.Move && this.SourceDraggedOrCutOrCopied) { // Temporarily allow duplicate links to enable cut-paste or drag-move of links within the project. // This won't happen when the source is another project because this.SourceDraggedOrCutOrCopied won't get set. this.AllowDuplicateLinks = true; } string[] filesDroppedAsArray = filesDropped.ToArray(); HierarchyNode node = (targetNode == null) ? this : targetNode; // For directory based projects the content of the clipboard is a double-NULL terminated list of Projref strings. if (isWindowsFormat) { // This is the code path when source is windows explorer VSADDRESULT[] vsaddresults = new VSADDRESULT[1]; vsaddresults[0] = VSADDRESULT.ADDRESULT_Failure; int addResult = AddItem(node.ID, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, null, (uint)filesDropped.Count, filesDroppedAsArray, IntPtr.Zero, vsaddresults); if (addResult != VSConstants.S_OK && addResult != VSConstants.S_FALSE && addResult != (int)OleConstants.OLECMDERR_E_CANCELED && vsaddresults[0] != VSADDRESULT.ADDRESULT_Success) { ErrorHandler.ThrowOnFailure(addResult); } return dropDataType; } else { if (AddFilesFromProjectReferences(node, filesDroppedAsArray, (uint)dropEffect)) { return dropDataType; } } } finally { this.AllowDuplicateLinks = saveAllowDuplicateLinks; } } this.dataWasCut = false; // If we reached this point then the drop data must be set to None. // Otherwise the OnPaste will be called with a valid DropData and that would actually delete the item. return DropDataType.None; }
/// <summary> /// Handle the Paste operation to a targetNode /// </summary> protected internal override int PasteFromClipboard(HierarchyNode targetNode) { int returnValue; try { this.isInPasteOrDrop = true; this.dropAsCopy = !this.dataWasCut; returnValue = PasteFromClipboardCore(targetNode); } finally { this.isInPasteOrDrop = false; this.dropAsCopy = false; this.pasteAsNonMemberItem = false; } return returnValue; }
/// <summary> /// Recursive method that walk a hierarchy and add items it find to our project. /// Note that this is meant as an helper to the Copy&Paste/Drag&Drop functionality. /// </summary> /// <param name="sourceHierarchy">Hierarchy to walk</param> /// <param name="itemId">Item ID where to start walking the hierarchy</param> /// <param name="targetNode">Node to start adding to</param> /// <param name="name">Folder name to use</param> /// <param name="addSiblings">Typically false on first call and true after that</param> /// <remarks>Use this method when the folder name to add items to is not /// the same as the source.</remarks> protected virtual void WalkSourceProjectAndAdd(IVsHierarchy sourceHierarchy, uint itemId, HierarchyNode targetNode, string name, bool addSiblings) { // Before we start the walk, add the current node object variant = null; HierarchyNode newNode = targetNode; if (itemId != VSConstants.VSITEMID_NIL) { // Calculate the corresponding path in our project string targetPath = Path.Combine(GetBaseDirectoryForAddingFiles(targetNode), name); // See if this is a linked item (file can be linked, not folders) VSADDITEMOPERATION addItemOp = VSADDITEMOPERATION.VSADDITEMOP_OPENFILE; ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_BrowseObject, out variant), VSConstants.E_NOTIMPL); VSLangProj.FileProperties fileProperties = variant as VSLangProj.FileProperties; if (fileProperties != null && fileProperties.IsLink) { addItemOp = VSADDITEMOPERATION.VSADDITEMOP_LINKTOFILE; targetPath = fileProperties.FullPath; } ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_IsNonMemberItem, out variant), VSConstants.E_NOTIMPL); bool oldPasteAsNonMemberItem = this.PasteAsNonMemberItem; try { this.pasteAsNonMemberItem = variant != null && (bool)variant; newNode = AddNodeIfTargetExistInStorage(targetNode, name, targetPath, addItemOp); } finally { this.pasteAsNonMemberItem = oldPasteAsNonMemberItem; } // Start with child nodes (depth first) variant = null; ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_FirstVisibleChild, out variant)); uint currentItemID; if (variant is int) { currentItemID = (uint)System.BitConverter.ToUInt32(System.BitConverter.GetBytes((int)variant), 0); } else { currentItemID = (uint)variant; } WalkSourceProjectAndAdd(sourceHierarchy, currentItemID, newNode, true); if (addSiblings) { // Then look at siblings currentItemID = itemId; while (currentItemID != VSConstants.VSITEMID_NIL) { variant = null; ErrorHandler.ThrowOnFailure(sourceHierarchy.GetProperty(currentItemID, (int)__VSHPROPID.VSHPROPID_NextVisibleSibling, out variant)); if (variant is int) { currentItemID = (uint)System.BitConverter.ToUInt32(System.BitConverter.GetBytes((int)variant), 0); } else { currentItemID = (uint)variant; } WalkSourceProjectAndAdd(sourceHierarchy, currentItemID, targetNode, false); } } } }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.OnItemsAppended"]/*' /> public void OnItemsAppended(HierarchyNode parent){ HierarchyNode foo; foo = this.projectMgr == null ? this : this.projectMgr; try{ foreach (IVsHierarchyEvents sink in foo.hierarchyEventSinks){ sink.OnItemsAppended(parent.hierarchyId); } } catch{ } }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.OnItemAdded"]/*' /> public void OnItemAdded(HierarchyNode parent, HierarchyNode child){ HierarchyNode foo; foo = this.projectMgr == null ? this : this.projectMgr; HierarchyNode prev = child.PreviousSibling; uint prevId = (prev != null) ? prev.hierarchyId : VsConstants.VSITEMID_NIL; try{ foreach (IVsHierarchyEvents sink in foo.hierarchyEventSinks){ sink.OnItemAdded(parent.hierarchyId, prevId, child.hierarchyId); } } catch{ } }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.AddNewFolder"]/*' /> /// <summary> /// Get's called to a add a new Folder to the project hierarchy. Opens the dialog to do so and /// creates the physical representation /// </summary> /// <returns></returns> public int AddNewFolder(){ // first generate a new folder name... try{ string relFolder; object dummy = null; IVsProject3 project = (IVsProject3)this.projectMgr; IVsUIHierarchyWindow uiWindow = this.projectMgr.GetIVsUIHierarchyWindow(VsConstants.Guid_SolutionExplorer); project.GenerateUniqueItemName(this.hierarchyId, "", "", out relFolder); if (this != this.projectMgr){ // add this guys relpath to it... relFolder = this.xmlNode.GetAttribute("RelPath") + relFolder; } // create the project part of it, the xml in the xsproj file XmlElement e = this.projectMgr.AddFolderNodeToProject(relFolder); HierarchyNode child = new HierarchyNode(this.projectMgr, HierarchyNodeType.Folder, e); this.AddChild(child); child.CreateDirectory(); // we need to get into label edit mode now... // so first select the new guy... uiWindow.ExpandItem(this.projectMgr, child.hierarchyId, EXPANDFLAGS.EXPF_SelectItem); // them post the rename command to the shell. Folder verification and creation will // happen in the setlabel code... this.projectMgr.UIShell.PostExecCommand(ref VsConstants.guidStandardCommandSet97, (uint)VsCommands.Rename, 0, ref dummy); } catch{ } return 0; }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.RemoveChild"]/*' /> public virtual void RemoveChild(HierarchyNode node){ this.projectMgr.ItemIdMap.Remove(node); HierarchyNode last = null; for (HierarchyNode n = this.firstChild; n != null; n = n.nextSibling){ if (n == node){ if (last != null){ last.nextSibling = n.nextSibling; } if (n == this.lastChild){ if (last == this.lastChild){ this.lastChild = null; } else{ this.lastChild = last; } } if (n == this.firstChild){ this.firstChild = n.nextSibling; } return; } last = n; } throw new InvalidOperationException("Node not found"); }
public void Set(HierarchyNode node) { selection.Clear(); selection.Add(new NodeProperties(node)); }
public void Add(HierarchyNode node) { selection.Add(new NodeProperties(node)); }
public SelectionContainer(HierarchyNode node) { selection = new ArrayList(); selection.Add(new NodeProperties(node)); }
/// <summary> /// This is used to recursively add a folder from an other project. /// Note that while we copy the folder content completely, we only /// add to the project items which are part of the source project. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> /// <param name="dropEffect">The drop effect</param> /// <param name="validateOnly">If true, no action is actually taken. Only checks for error cases.</param> protected internal virtual void AddFolderFromOtherProject(string folderToAdd, HierarchyNode targetNode, uint dropEffect, bool validateOnly) { if (String.IsNullOrEmpty(folderToAdd)) throw new ArgumentNullException("folderToAdd"); if (targetNode == null) throw new ArgumentNullException("targetNode"); // get the source path Guid projectInstanceGuid; string folder = GetSourceFromFolderReference(folderToAdd, out projectInstanceGuid); string folderNoTrailingSlash = folder.Substring(0, folder.Length - 1); // Get the target path string folderName = Path.GetFileName(Path.GetDirectoryName(folder)); string newFolderBaseDir = GetBaseDirectoryForAddingFiles(targetNode); string targetPath = Path.Combine(newFolderBaseDir, folderName); bool bPathsSame = NativeMethods.IsSamePath(folderNoTrailingSlash, targetPath); if (!bPathsSame && targetPath.StartsWith(folder, StringComparison.Ordinal)) { throw new DestionPathSubfolderOfSourceException(folderName); } // If these paths are the same, allow it and prepend "Copy of" only // if it was copied to clipboard or dragged with copy effect if (bPathsSame && (!this.SourceDragged && !this.dataWasCut) || (this.SourceDragged && dropEffect == (uint)DropEffect.Copy)) { // When validating, do not find a free directory // Validation is finished at this point. if (validateOnly) return; int copyNumber = 0; string originalFolderName = folderName; while (Directory.Exists(targetPath)) { copyNumber++; if (copyNumber == 1) { folderName = SR.GetString(SR.CopyOfFile, originalFolderName); } else { folderName = SR.GetString(SR.CopyNOfFile, copyNumber, originalFolderName); } targetPath = Path.Combine(newFolderBaseDir, folderName); } } // Do not perform copy if paths are still the same. if (NativeMethods.IsSamePath(folderNoTrailingSlash, targetPath)) { throw new DestionPathSameAsSourceException(folderName); } if (Directory.Exists(targetPath)) { throw new DestinationFolderAlreadyExists(folderName); } if (validateOnly) return; // Recursively copy the directory to the new location Utilities.RecursivelyCopyDirectory(folder, targetPath); // Retrieve the project from which the items are being copied IVsHierarchy sourceHierarchy; IVsSolution solution = (IVsSolution)GetService(typeof(SVsSolution)); ErrorHandler.ThrowOnFailure(solution.GetProjectOfGuid(ref projectInstanceGuid, out sourceHierarchy)); // Then retrieve the item ID of the item to copy uint itemID = VSConstants.VSITEMID_ROOT; ErrorHandler.ThrowOnFailure(sourceHierarchy.ParseCanonicalName(folder, out itemID)); // Ensure we don't end up in an endless recursion if (Utilities.IsSameComObject(this, sourceHierarchy)) { HierarchyNode cursorNode = targetNode; while (cursorNode != null) { if (String.Compare(folder, cursorNode.GetMkDocument(), StringComparison.OrdinalIgnoreCase) == 0) throw new ApplicationException(); cursorNode = cursorNode.Parent; } } // Now walk the source project hierarchy to see which node needs to be added. WalkSourceProjectAndAdd(sourceHierarchy, itemID, targetNode, folderName, false); }
/// <summary> /// Recursive method that walk a hierarchy and add items it find to our project. /// Note that this is meant as an helper to the Copy&Paste/Drag&Drop functionality. /// </summary> /// <param name="sourceHierarchy">Hierarchy to walk</param> /// <param name="itemId">Item ID where to start walking the hierarchy</param> /// <param name="targetNode">Node to start adding to</param> /// <param name="addSiblings">Typically false on first call and true after that</param> protected virtual void WalkSourceProjectAndAdd(IVsHierarchy sourceHierarchy, uint itemId, HierarchyNode targetNode, bool addSiblings) { // Before we start the walk, add the current node if (itemId != VSConstants.VSITEMID_NIL) { string source; ErrorHandler.ThrowOnFailure(((IVsProject)sourceHierarchy).GetMkDocument(itemId, out source)); string name = Path.GetFileName(source.TrimEnd(new char[] { '/', '\\' })); WalkSourceProjectAndAdd(sourceHierarchy, itemId, targetNode, name, addSiblings); } }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.OnPropertyChanged"]/*' /> public void OnPropertyChanged(HierarchyNode node, int propid, uint flags){ HierarchyNode foo; foo = this.projectMgr == null ? this : this.projectMgr; foreach (IVsHierarchyEvents sink in foo.hierarchyEventSinks){ sink.OnPropertyChanged(node.hierarchyId, propid, flags); } }
/// <summary> /// Add an existing item (file/folder) to the project if it already exist in our storage. /// </summary> /// <param name="parentNode">Node to that this item to</param> /// <param name="name">Name of the item being added</param> /// <param name="targetPath">Path of the item being added</param> /// <returns>Node that was added</returns> protected virtual HierarchyNode AddNodeIfTargetExistInStorage(HierarchyNode parentNode, string name, string targetPath, VSADDITEMOPERATION addItemOp) { HierarchyNode newNode = parentNode; // If the file/directory exist, add a node for it if (addItemOp == VSADDITEMOPERATION.VSADDITEMOP_LINKTOFILE || File.Exists(targetPath)) { VSADDRESULT[] result = new VSADDRESULT[1]; ErrorHandler.ThrowOnFailure(this.AddItem(parentNode.ID, addItemOp, name, 1, new string[] { targetPath }, IntPtr.Zero, result)); if (result[0] != VSADDRESULT.ADDRESULT_Success) throw new ApplicationException(); newNode = this.FindChild(targetPath); if (newNode == null) throw new ApplicationException(); } else if (Directory.Exists(targetPath)) { newNode = this.CreateFolderNodes(targetPath); } return newNode; }
/// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.OnInvalidateItems"]/*' /> public void OnInvalidateItems(HierarchyNode parent){ HierarchyNode foo; foo = this.projectMgr == null ? this : this.projectMgr; foreach (IVsHierarchyEvents sink in foo.hierarchyEventSinks){ sink.OnInvalidateItems(parent.hierarchyId); } }
/// <summary> /// Handle the Paste operation to a targetNode. Do not call directly /// outside of PasteFromClipboard. /// </summary> private int PasteFromClipboardCore(HierarchyNode targetNode) { int returnValue = (int)OleConstants.OLECMDERR_E_NOTSUPPORTED; //Get the clipboardhelper service and use it after processing dataobject IVsUIHierWinClipboardHelper clipboardHelper = (IVsUIHierWinClipboardHelper)GetService(typeof(SVsUIHierWinClipboardHelper)); if (clipboardHelper == null) { return VSConstants.E_FAIL; } try { //Get dataobject from clipboard IOleDataObject dataObject = null; ErrorHandler.ThrowOnFailure(UnsafeNativeMethods.OleGetClipboard(out dataObject)); if (dataObject == null) { return VSConstants.E_UNEXPECTED; } DropEffect dropEffect = DropEffect.None; DropDataType dropDataType = DropDataType.None; try { this.SourceDraggedOrCutOrCopied = this.dataWasCut; dropDataType = this.ProcessSelectionDataObject(dataObject, targetNode.GetDragTargetHandlerNode(), 0); dropEffect = this.QueryDropEffect(dropDataType, 0); } catch (ExternalException e) { Trace.WriteLine("Exception : " + e.Message); // If it is a drop from windows and we get any kind of error ignore it. This // prevents bogus messages from the shell from being displayed if (dropDataType != DropDataType.Shell) { throw e; } } finally { // Inform VS (UiHierarchyWindow) of the paste returnValue = clipboardHelper.Paste(dataObject, (uint)dropEffect); } } catch (COMException e) { Trace.WriteLine("Exception : " + e.Message); returnValue = e.ErrorCode; } return returnValue; }
////////////////////////////////////////////////////////////////////////////////////////// // // AddChild - add a node, sorted in the right location. // ////////////////////////////////////////////////////////////////////////////////////////// /// <include file='doc\Hierarchy.uex' path='docs/doc[@for="HierarchyNode.AddChild"]/*' /> public virtual void AddChild(HierarchyNode node){ // make sure it's in the map. if (node.hierarchyId < this.projectMgr.ItemIdMap.Length && this.projectMgr.ItemIdMap[node.hierarchyId] == null){ // reuse our hierarchy id if possible. this.projectMgr.ItemIdMap.SetAt(node.hierarchyId, this); } else{ node.hierarchyId = this.projectMgr.ItemIdMap.Add(node); } HierarchyNode previous = null; for (HierarchyNode n = this.firstChild; n != null; n = n.nextSibling){ if (n.CompareTo(node) > 0) break; previous = n; } // insert "node" after "previous". if (previous != null){ node.nextSibling = previous.nextSibling; previous.nextSibling = node; if (previous == this.lastChild) this.lastChild = node; } else{ if (this.lastChild == null){ this.lastChild = node; } node.nextSibling = this.firstChild; this.firstChild = node; } node.parentNode = this; this.OnItemAdded(this, node); }
public ReferenceNodeProperties(HierarchyNode node) : base(node) { }
/// <include file='doc\PropertyPages.uex' path='docs/doc[@for="NodeProperties.NodeProperties"]/*' /> public NodeProperties(HierarchyNode node) { this.Node = node; project = node.ProjectMgr; }
public DependentFileNodeProperties(HierarchyNode node) : base(node) { }
/// <include file='doc\PropertyPages.uex' path='docs/doc[@for="FileProperties.FileProperties"]/*' /> public FileProperties(HierarchyNode node) : base(node) { }
public LinkedFileNodeProperties(HierarchyNode node) : base(node) { }
/// <summary> /// Moves files from one part of our project to another. /// </summary> /// <param name="targetNode">the targetHandler node</param> /// <param name="projectReferences">List of projectref string</param> /// <param name="dropEffect">The drop effect</param> /// <returns>true if succeeded</returns> internal bool AddFilesFromProjectReferences(HierarchyNode targetNode, string[] projectReferences, uint dropEffect) { // Validate input if (projectReferences == null) { throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "projectReferences"); } if (targetNode == null) { throw new InvalidOperationException(); } // Build a list bool bSourceProjectIsNotThisProject = false; foreach (string projectReference in projectReferences) { if (String.IsNullOrEmpty(projectReference)) { // bad projectref, bail out return false; } IVsSolution solution = this.GetService(typeof(IVsSolution)) as IVsSolution; if (solution == null) { throw new InvalidOperationException(); } if (projectReference.EndsWith("/", StringComparison.Ordinal) || projectReference.EndsWith("\\", StringComparison.Ordinal)) { Guid projectInstanceGuid; string folder = GetSourceFromFolderReference(projectReference, out projectInstanceGuid); string folderNoTrailingSlash = folder.Substring(0, folder.Length - 1); // Check if the source is not this project if it hasn't been // determined yet. if(!bSourceProjectIsNotThisProject) { if (projectInstanceGuid != this.ProjectIDGuid) { bSourceProjectIsNotThisProject = true; } } string folderName = Path.GetFileName(Path.GetDirectoryName(folder)); string newFolderBaseDir = GetBaseDirectoryForAddingFiles(targetNode); string targetPath = Path.Combine(newFolderBaseDir, folderName); DragDropItem newItem = new DragDropItem(); newItem.reference = projectReference; newItem.source = folderNoTrailingSlash; newItem.destination = targetPath; newItem.destinationExists = Directory.Exists(targetPath); newItem.isFolder = true; newItem.sourceDirMatchesDestDir = NativeMethods.IsSamePath(folderNoTrailingSlash, targetPath); dropItems.Add(newItem); } else { uint itemidLoc; IVsHierarchy hierarchy; string str; VSUPDATEPROJREFREASON[] reason = new VSUPDATEPROJREFREASON[1]; ErrorHandler.ThrowOnFailure(solution.GetItemOfProjref(projectReference, out hierarchy, out itemidLoc, out str, reason)); if (hierarchy == null) { throw new InvalidOperationException(); } // This will throw invalid cast exception if the hierrachy is not a project. IVsProject project = (IVsProject)hierarchy; string moniker; ErrorHandler.ThrowOnFailure(project.GetMkDocument(itemidLoc, out moniker)); HierarchyNode n = targetNode; while ((!(n is ProjectNode)) && (!(n is FolderNode)) && (!this.CanFileNodesHaveChilds || !(n is FileNode))) { n = n.Parent; } Guid projectInstanceGuid; solution.GetGuidOfProject(hierarchy, out projectInstanceGuid); // Check if the source is not this project if it hasn't been // determined yet. if (!bSourceProjectIsNotThisProject) { if (projectInstanceGuid != this.ProjectIDGuid) { bSourceProjectIsNotThisProject = true; } } string filename = Path.GetFileName(moniker); string destination = Path.Combine(this.GetBaseDirectoryForAddingFiles(n), filename); string sourcedir = Path.GetDirectoryName(moniker); string destdir = Path.GetDirectoryName(destination); DragDropItem newItem = new DragDropItem(); newItem.reference = projectReference; newItem.source = moniker; newItem.destination = destination; newItem.destinationExists = File.Exists(destination); newItem.isFolder = false; newItem.sourceDirMatchesDestDir = NativeMethods.IsSamePath(sourcedir, destdir); dropItems.Add(newItem); } } // We don't want to copy files that are within any selected directories foreach (DragDropItem dropItem1 in dropItems) { if (dropItem1.isFolder) { foreach (DragDropItem dropItem2 in dropItems) { // If this item is underneath a folder also being copied // or moved, then remove it from the list of items to be // copied or moved since the copy/move operation of the // containing folder will handle it. if (!dropItem2.source.Equals(dropItem1.source) && dropItem2.source.StartsWith(dropItem1.source, StringComparison.Ordinal)) { // set userCancelled so that this item gets skipped dropItem2.userCancelled = true; } } } } // Check for error cases foreach (DragDropItem dropItem in dropItems) { if (dropItem.userCancelled) continue; if (dropItem.isFolder) { try { AddFolderFromOtherProject(dropItem.reference, targetNode, dropEffect, true); } catch (CopyPasteException e) { string errorMessage = e.Message; if (!Utilities.IsInAutomationFunction(this.ProjectMgr.Site)) { string title = null; OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL; OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK; OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; VsShellUtilities.ShowMessageBox(this.ProjectMgr.Site, title, errorMessage, icon, buttons, defaultButton); return false; } else { throw new InvalidOperationException(errorMessage); } } } else { try { if (dropItem.sourceDirMatchesDestDir && dropEffect == (uint)DropEffect.Move) { throw new DestionPathSameAsSourceException(filename); } bool bWillHaveCopyOfPrepended = dropItem.sourceDirMatchesDestDir && dropEffect == (uint)DropEffect.Copy; // Check if overwriting is possible. // If not, a dialog box will be shown by SystemCanOverwriteExistingItem // and we should stop processing items. if (!bWillHaveCopyOfPrepended && dropItem.destinationExists && this.SystemCanOverwriteExistingItem(dropItem.source, dropItem.destination) != VSConstants.S_OK) { return false; } } catch (DestionPathSameAsSourceException e) { string errorMessage = e.Message; if (!Utilities.IsInAutomationFunction(this.ProjectMgr.Site)) { string title = null; OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL; OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK; OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST; VsShellUtilities.ShowMessageBox(this.ProjectMgr.Site, title, errorMessage, icon, buttons, defaultButton); return false; } else { throw new InvalidOperationException(errorMessage); } } } } bool bAnyWereCancelled = false; bool bDoApplyAll = false; DialogResult applyAllResult = DialogResult.No; // Prompt for files to be overwritten for (int i = 0; i < dropItems.Count; i++) { DragDropItem dropItem = dropItems[i]; if (dropItem.userCancelled) continue; // If the source dir matches the dest dir and we are doing copy // then no overwriting will occur. Instead, "Copy of " will be // prepended. if (dropItem.destinationExists && !(dropItem.sourceDirMatchesDestDir && dropEffect == (uint)DropEffect.Copy)) { string message = SR.GetString(SR.FileAlreadyExists, Path.GetFileName(dropItem.destination)); string title = SR.GetString(SR.FileAlreadyExistsCaption); DialogResult msgboxResult; if (bDoApplyAll) { msgboxResult = applyAllResult; } else { bool bApplyAllChecked; msgboxResult = FileOverwriteDialog.LaunchFileOverwriteDialog(this.Site, message, title, null, FileOverwriteDialog.DefaultButton.Yes, out bApplyAllChecked); if(bApplyAllChecked) { bDoApplyAll = true; applyAllResult = msgboxResult; } } if (msgboxResult == DialogResult.No) { dropItem.userCancelled = true; bAnyWereCancelled = true; } else if (msgboxResult != DialogResult.Yes) { // user cancelled the whole thing return false; } } } // Iteratively add files from projectref foreach (DragDropItem dropItem in dropItems) { if (dropItem.userCancelled) continue; if (dropItem.isFolder) { AddFolderFromOtherProject(dropItem.reference, targetNode, dropEffect); } else { bool oldHandledOverwrite = this.alreadyHandledOverwritePrompts; this.alreadyHandledOverwritePrompts = true; try { if (!AddFileToNodeFromProjectReference(dropItem.reference, targetNode)) { return false; } } finally { this.alreadyHandledOverwritePrompts = oldHandledOverwrite; } } } // If any items were cancelled and the source and target projects // differ, return false here so that none of the source items are // removed. It would be incorrect to remove all of the source // items at this point. if (bSourceProjectIsNotThisProject && bAnyWereCancelled) return false; return true; }
public BaseFileNodeProperties(HierarchyNode node) : base(node) { }
/// <summary> /// This is used to recursively add a folder from an other project. /// Note that while we copy the folder content completely, we only /// add to the project items which are part of the source project. /// </summary> /// <param name="folderToAdd">Project reference (from data object) using the format: {Guid}|project|folderPath</param> /// <param name="targetNode">Node to add the new folder to</param> /// <param name="dropEffect">The drop effect</param> protected internal virtual void AddFolderFromOtherProject(string folderToAdd, HierarchyNode targetNode, uint dropEffect) { AddFolderFromOtherProject(folderToAdd, targetNode, dropEffect, false); }