private static void MoveReferencedFileToDirectory(ReferencedFileSave referencedFileSave, string targetDirectory) { // Things to do: // 1 Move the TreeNode from one parent TreeNode to another UPDATE: We will just refresh the UI for the Element or GlobalContent // 2 Move the file from one folder to another // 3 Remove the BuildItems from the project and add them back in the VisualStudio project // 4 Change the ReferencedFileSave's name // 5 Re-generate the containing Element (Screen or Entity) // 6 Save everything string oldNodeText = referencedFileSave.Name.Replace("/", "\\"); string newNodeText = FlatRedBall.IO.FileManager.MakeRelative(targetDirectory, ProjectManager.ProjectBase.GetAbsoluteContentFolder()) + FileManager.RemovePath(referencedFileSave.Name); newNodeText = newNodeText.Replace("/", "\\"); string oldFileName = ProjectManager.MakeAbsolute(referencedFileSave.Name, true); string targetFile = targetDirectory + FileManager.RemovePath(oldFileName); bool canMove = true; // There's so much error checking and validation that we // could/should do here, but man, I just can't spend forever // on it because I need to get the game I'm working on moving forward // But I'm going to at least improve it a little bit by having the referenced // files get copied over. Dictionary <string, string> mOldNewDependencyFileDictionary = new Dictionary <string, string>(); List <string> referencedFiles = ContentParser.GetFilesReferencedByAsset(oldFileName, TopLevelOrRecursive.Recursive); string oldDirectoryFull = FileManager.GetDirectory(oldFileName); foreach (string file in referencedFiles) { string relativeToRfs = FileManager.MakeRelative(file, FileManager.GetDirectory(oldFileName)); string targetReferencedFileName = targetDirectory + relativeToRfs; mOldNewDependencyFileDictionary.Add(file, targetReferencedFileName); if (!FileManager.IsRelativeTo(targetReferencedFileName, targetDirectory)) { MessageBox.Show("The file\n\n" + file + "\n\nis not relative to the file being moved, so it cannot be moved. You must manually move these files and manually update the file reference."); canMove = false; break; } } if (canMove && File.Exists(targetFile)) { MessageBox.Show("There is already a file by this name located in the directory you're trying to move to."); canMove = false; } if (canMove) { foreach (KeyValuePair <string, string> kvp in mOldNewDependencyFileDictionary) { if (File.Exists(kvp.Value)) { MessageBox.Show("Can't move the file because a dependency will be moved to\n\n" + kvp.Value + "\n\nand a file already exists there."); canMove = false; break; } } } if (canMove) { // 1 Move the TreeNode from one parent TreeNode to another //treeNodeMoving.Parent.Nodes.Remove(treeNodeMoving); //targetNode.Nodes.Add(treeNodeMoving); // This is updated at the bottom of this method // In case it doesn't exist System.IO.Directory.CreateDirectory(FileManager.GetDirectory(targetFile)); // 2 Move the file from one folder to another File.Move(oldFileName, targetFile); foreach (KeyValuePair <string, string> kvp in mOldNewDependencyFileDictionary) { File.Move(kvp.Key, kvp.Value); } // 3 Remove the BuildItems from the project and add them back in the VisualStudio project ProjectBase projectBase = ProjectManager.ProjectBase; if (ProjectManager.ContentProject != null) { projectBase = ProjectManager.ContentProject; } ProjectManager.RemoveItemFromProject(projectBase, oldNodeText, false); projectBase.AddContentBuildItem(targetFile); foreach (KeyValuePair <string, string> kvp in mOldNewDependencyFileDictionary) { string fileFileRelativeToProject = FileManager.MakeRelative(kvp.Key, projectBase.Directory); ProjectManager.RemoveItemFromProject(projectBase, fileFileRelativeToProject, false); projectBase.AddContentBuildItem(kvp.Value); } // TODO: This should also check to see if something else is referencing this content. // I'm going to write it to not make this check now since I'm just getting the initial system set up // 4 Change the ReferencedFileSave's name referencedFileSave.SetNameNoCall(newNodeText.Replace("\\", "/")); // No need for this, it'll get updated automatically // treeNodeMoving.Text = newNodeText; // 5 Re-generate the containing Element (Screen or Entity) if (EditorLogic.CurrentElement != null) { CodeWriter.GenerateCode(EditorLogic.CurrentElement); } else { GlobalContentCodeGenerator.UpdateLoadGlobalContentCode(); } // The new 1: Update if (EditorLogic.CurrentElement != null) { EditorLogic.CurrentElementTreeNode.UpdateReferencedTreeNodes(); } else { ElementViewWindow.UpdateGlobalContentTreeNodes(false); } // 6 Save everything GluxCommands.Self.SaveGlux(); ProjectManager.SaveProjects(); } }
private static void MoveReferencedFile(TreeNode treeNodeMoving, TreeNode targetNode) { var response = GeneralResponse.SuccessfulResponse; while (targetNode != null && targetNode.IsReferencedFile()) { targetNode = targetNode.Parent; } // If the user drops a file on a Screen or Entity, let's allow them to // complete the operation on the Files node if (targetNode is BaseElementTreeNode) { targetNode = ((BaseElementTreeNode)targetNode).FilesTreeNode; } ReferencedFileSave referencedFileSave = treeNodeMoving.Tag as ReferencedFileSave; if (!targetNode.IsFilesContainerNode() && !targetNode.IsFolderInFilesContainerNode() && !targetNode.IsFolderForGlobalContentFiles() && !targetNode.IsNamedObjectNode() && !targetNode.IsRootNamedObjectNode()) { response.Fail(@"Can't drop this file here"); } else if (!string.IsNullOrEmpty(referencedFileSave.SourceFile) || referencedFileSave.SourceFileCache.Count != 0) { response.Fail("Can't move the file\n\n" + referencedFileSave.Name + "\n\nbecause it has source-referencing files. These sources will be broken " + "if the file is moved. You will need to manually move the file, modify the source references, remove this file, then add the newly-created file."); } if (response.Succeeded) { if (targetNode.IsGlobalContentContainerNode()) { if (targetNode.GetContainingElementTreeNode() == null) { string targetDirectory = ProjectManager.MakeAbsolute(targetNode.GetRelativePath(), true); MoveReferencedFileToDirectory(referencedFileSave, targetDirectory); } else { DragAddFileToGlobalContent(treeNodeMoving, referencedFileSave); // This means the user wants to add the file // to global content. } } else if (targetNode.IsFolderForGlobalContentFiles()) { string targetDirectory = ProjectManager.MakeAbsolute(targetNode.GetRelativePath(), true); MoveReferencedFileToDirectory(referencedFileSave, targetDirectory); } else if (targetNode.IsRootNamedObjectNode()) { AddObjectViewModel viewModel = new AddObjectViewModel(); viewModel.SourceType = SourceType.File; viewModel.SourceFile = (treeNodeMoving.Tag as ReferencedFileSave).Name; GlueCommands.Self.DialogCommands.ShowAddNewObjectDialog(viewModel); } else if (targetNode.IsNamedObjectNode() && // dropping on an object in the same element targetNode.GetContainingElementTreeNode() == treeNodeMoving.GetContainingElementTreeNode()) { response = HandleDroppingFileOnObjectInSameElement(targetNode, referencedFileSave); } //if (targetNode.IsFolderInFilesContainerNode() || targetNode.IsFilesContainerNode()) else { // See if we're moving the RFS from one Element to another IElement container = ObjectFinder.Self.GetElementContaining(referencedFileSave); TreeNode elementTreeNodeDroppingIn = targetNode.GetContainingElementTreeNode(); IElement elementDroppingIn = null; if (elementTreeNodeDroppingIn != null) { // User didn't drop on an entity, but instead on a node within the entity. // Let's check if it's a subfolder. If so, we need to tell the user that we // can't add the file in a subfolder. if (targetNode.IsFolderInFilesContainerNode()) { response.Message = "Shared files cannot be added to subfolders, so it will be added directly to \"Files\""; } elementDroppingIn = elementTreeNodeDroppingIn.Tag as IElement; } if (container != elementDroppingIn) { // Make sure the target element is not named the same as the file itself. // For example, dropping a file called Level1.tmx in a screen called Level1. // This will not compile so we shouldn't allow it. var areNamedTheSame = elementDroppingIn.GetStrippedName() == referencedFileSave.GetInstanceName(); if (areNamedTheSame) { response.Fail($"The file {referencedFileSave.GetInstanceName()} has the same name as the target screen. it will not be added since this is not allowed."); } if (response.Succeeded) { ElementViewWindow.SelectedNode = targetNode; string absoluteFileName = ProjectManager.MakeAbsolute(referencedFileSave.Name, true); string creationReport; string errorMessage; var newlyCreatedFile = ElementCommands.Self.CreateReferencedFileSaveForExistingFile(elementDroppingIn, null, absoluteFileName, PromptHandleEnum.Prompt, referencedFileSave.GetAssetTypeInfo(), out creationReport, out errorMessage); ElementViewWindow.UpdateChangedElements(); if (!String.IsNullOrEmpty(errorMessage)) { MessageBox.Show(errorMessage); } else if (newlyCreatedFile != null) { GlueCommands.Self.TreeNodeCommands.SelectTreeNode(newlyCreatedFile); } } } else { // Not moving into or out of an element string targetDirectory = ProjectManager.MakeAbsolute(targetNode.GetRelativePath(), true); MoveReferencedFileToDirectory(referencedFileSave, targetDirectory); } } } if (!string.IsNullOrEmpty(response.Message)) { MessageBox.Show(response.Message); } }