protected override int AfterSaveItemAs(IntPtr docData, string newFilePath)
{
if(String.IsNullOrEmpty(newFilePath))
{
throw new ArgumentException(SR.GetString(SR.ParameterCannotBeNullOrEmpty, CultureInfo.CurrentUICulture), "newFilePath");
}
int returnCode = VSConstants.S_OK;
newFilePath = newFilePath.Trim();
//Identify if Path or FileName are the same for old and new file
string newDirectoryName = Path.GetDirectoryName(newFilePath);
Uri newDirectoryUri = new Uri(newDirectoryName);
string newCanonicalDirectoryName = newDirectoryUri.LocalPath;
newCanonicalDirectoryName = newCanonicalDirectoryName.TrimEnd(Path.DirectorySeparatorChar);
string oldCanonicalDirectoryName = new Uri(Path.GetDirectoryName(this.GetMKDocument())).LocalPath;
oldCanonicalDirectoryName = oldCanonicalDirectoryName.TrimEnd(Path.DirectorySeparatorChar);
string errorMessage = String.Empty;
bool isSamePath = NativeMethods.IsSamePath(newCanonicalDirectoryName, oldCanonicalDirectoryName);
bool isSameFile = NativeMethods.IsSamePath(newFilePath, this.Url);
string linkPath = null;
string projectCannonicalDirecoryName = new Uri(this.ProjectManager.ProjectFolder).LocalPath;
projectCannonicalDirecoryName = projectCannonicalDirecoryName.TrimEnd(Path.DirectorySeparatorChar);
if(!isSamePath && newCanonicalDirectoryName.IndexOf(projectCannonicalDirecoryName, StringComparison.OrdinalIgnoreCase) == -1)
{
// Link the new file into the same location in the project hierarchy it was before.
string oldRelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Link);
if (String.IsNullOrEmpty(oldRelPath))
{
oldRelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
}
newDirectoryName = Path.GetDirectoryName(oldRelPath);
linkPath = Path.Combine(newDirectoryName, Path.GetFileName(newFilePath));
}
//Get target container
HierarchyNode targetContainer = null;
if(isSamePath)
{
targetContainer = this.Parent;
}
else if(NativeMethods.IsSamePath(newCanonicalDirectoryName, projectCannonicalDirecoryName))
{
//the projectnode is the target container
targetContainer = this.ProjectManager;
}
else
{
//search for the target container among existing child nodes
targetContainer = this.ProjectManager.FindChild(newDirectoryName);
if(targetContainer != null && (targetContainer is FileNode))
{
// We already have a file node with this name in the hierarchy.
errorMessage = String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.FileAlreadyExistsAndCannotBeRenamed, CultureInfo.CurrentUICulture), Path.GetFileNameWithoutExtension(newFilePath));
throw new InvalidOperationException(errorMessage);
}
}
if(targetContainer == null)
{
// Add a chain of subdirectories to the project.
string relativeUri = PackageUtilities.GetPathDistance(this.ProjectManager.BaseUri.Uri, newDirectoryUri);
Debug.Assert(!String.IsNullOrEmpty(relativeUri) && relativeUri != newDirectoryUri.LocalPath, "Could not make pat distance of " + this.ProjectManager.BaseUri.Uri.LocalPath + " and " + newDirectoryUri);
targetContainer = this.ProjectManager.CreateFolderNodes(relativeUri);
}
Debug.Assert(targetContainer != null, "We should have found a target node by now");
//Suspend file changes while we rename the document
string oldrelPath = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
string oldName = Path.Combine(this.ProjectManager.ProjectFolder, oldrelPath);
SuspendFileChanges sfc = new SuspendFileChanges(this.ProjectManager.Site, oldName);
sfc.Suspend();
try
{
// Rename the node.
DocumentManager.UpdateCaption(this.ProjectManager.Site, Path.GetFileName(newFilePath), docData);
// Check if the file name was actually changed.
// In same cases (e.g. if the item is a file and the user has changed its encoding) this function
// is called even if there is no real rename.
if(!isSameFile || (this.Parent.Id != targetContainer.Id))
{
// The path of the file is changed or its parent is changed; in both cases we have
// to rename the item.
this.RenameFileNode(oldName, newFilePath, linkPath, targetContainer);
this.ItemNode.SetMetadata(ProjectFileConstants.Link, linkPath);
OnInvalidateItems(this.Parent);
}
}
catch(Exception e)
{
Trace.WriteLine("Exception : " + e.Message);
this.RecoverFromRenameFailure(newFilePath, oldrelPath);
throw;
}
finally
{
sfc.Resume();
}
return returnCode;
}