move file on rename

This commit is contained in:
Matt Parker
2025-10-31 18:57:37 +10:00
parent 3febc96aa9
commit fbe6b80cd9
2 changed files with 57 additions and 4 deletions

View File

@@ -137,6 +137,16 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
{ {
var sharpIdeFile = new SharpIdeFile(newFilePath, fileName, parentNode, []); var sharpIdeFile = new SharpIdeFile(newFilePath, fileName, parentNode, []);
var correctInsertionPosition = GetInsertionPosition(parentNode, sharpIdeFile);
parentNode.Files.Insert(correctInsertionPosition, sharpIdeFile);
SolutionModel.AllFiles.Add(sharpIdeFile);
await _fileChangedService.SharpIdeFileAdded(sharpIdeFile, contents);
return sharpIdeFile;
}
private static int GetInsertionPosition(IFolderOrProject parentNode, SharpIdeFile sharpIdeFile)
{
var correctInsertionPosition = parentNode.Files.list.BinarySearch(sharpIdeFile, SharpIdeFileComparer.Instance); var correctInsertionPosition = parentNode.Files.list.BinarySearch(sharpIdeFile, SharpIdeFileComparer.Instance);
if (correctInsertionPosition < 0) if (correctInsertionPosition < 0)
{ {
@@ -147,10 +157,25 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
throw new InvalidOperationException("File already exists in the containing folder or project"); throw new InvalidOperationException("File already exists in the containing folder or project");
} }
parentNode.Files.Insert(correctInsertionPosition, sharpIdeFile); return correctInsertionPosition;
SolutionModel.AllFiles.Add(sharpIdeFile); }
await _fileChangedService.SharpIdeFileAdded(sharpIdeFile, contents);
return sharpIdeFile; private static int GetMovePosition(IFolderOrProject parentNode, SharpIdeFile sharpIdeFile)
{
var correctInsertionPosition = parentNode.Files.list
.FindAll(x => x != sharpIdeFile) // TODO: Investigate allocations
.BinarySearch(sharpIdeFile, SharpIdeFileComparer.Instance);
if (correctInsertionPosition < 0)
{
correctInsertionPosition = ~correctInsertionPosition;
}
else
{
throw new InvalidOperationException("File already exists in the containing folder or project");
}
return correctInsertionPosition;
} }
public async Task RemoveFile(SharpIdeFile file) public async Task RemoveFile(SharpIdeFile file)
@@ -180,6 +205,10 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
var newFilePath = Path.Combine(Path.GetDirectoryName(oldPath)!, renamedFileName); var newFilePath = Path.Combine(Path.GetDirectoryName(oldPath)!, renamedFileName);
fileToRename.Name = renamedFileName; fileToRename.Name = renamedFileName;
fileToRename.Path = newFilePath; fileToRename.Path = newFilePath;
var parentFolderOrProject = (IFolderOrProject)fileToRename.Parent;
var currentPosition = parentFolderOrProject.Files.IndexOf(fileToRename);
var insertionPosition = GetMovePosition(parentFolderOrProject, fileToRename);
parentFolderOrProject.Files.Move(currentPosition, insertionPosition);
await _fileChangedService.SharpIdeFileRenamed(fileToRename, oldPath); await _fileChangedService.SharpIdeFileRenamed(fileToRename, oldPath);
return fileToRename; return fileToRename;
} }

View File

@@ -276,6 +276,7 @@ public partial class SolutionExplorerPanel : MarginContainer
.SubscribeAwait(async (innerEvent, ct) => await (innerEvent.Action switch .SubscribeAwait(async (innerEvent, ct) => await (innerEvent.Action switch
{ {
NotifyCollectionChangedAction.Add => this.InvokeAsync(() => innerEvent.NewItem.View.Value = CreateFileTreeItem(_tree, folderItem, innerEvent.NewItem.Value, innerEvent.NewStartingIndex)), NotifyCollectionChangedAction.Add => this.InvokeAsync(() => innerEvent.NewItem.View.Value = CreateFileTreeItem(_tree, folderItem, innerEvent.NewItem.Value, innerEvent.NewStartingIndex)),
NotifyCollectionChangedAction.Move => MoveTreeItem(_tree, innerEvent.NewItem.View, innerEvent.NewItem.Value, innerEvent.OldStartingIndex, innerEvent.NewStartingIndex),
NotifyCollectionChangedAction.Remove => FreeTreeItem(innerEvent.OldItem.View.Value), NotifyCollectionChangedAction.Remove => FreeTreeItem(innerEvent.OldItem.View.Value),
_ => Task.CompletedTask _ => Task.CompletedTask
})).AddTo(this); })).AddTo(this);
@@ -309,6 +310,29 @@ public partial class SolutionExplorerPanel : MarginContainer
return fileItem; return fileItem;
} }
private async Task MoveTreeItem(Tree tree, TreeItemContainer treeItemContainer, SharpIdeFile sharpIdeFile, int oldStartingIndex, int newStartingIndex)
{
if (oldStartingIndex == newStartingIndex) throw new InvalidOperationException("Old and new starting indexes are the same");
var treeItem = treeItemContainer.Value!;
var sharpIdeParent = sharpIdeFile.Parent as IFolderOrProject;
Guard.Against.Null(sharpIdeParent, nameof(sharpIdeParent));
var folderCount = sharpIdeParent.Folders.Count;
newStartingIndex += folderCount;
var treeParent = treeItem.GetParent()!;
await this.InvokeAsync(() =>
{
// The API for moving TreeItems is painful - we can only move an Item before or after another item
treeParent.RemoveChild(treeItem);
var newItem = tree.CreateItem(treeParent, newStartingIndex);
newItem.SetText(0, treeItem.GetText(0));
newItem.SetIcon(0, treeItem.GetIcon(0));
newItem.SetMetadata(0, treeItem.GetMetadata(0));
newItem.SetCustomColor(0, treeItem.GetCustomColor(0));
treeItemContainer.Value = newItem;
treeItem.Free();
});
}
private async Task FreeTreeItem(TreeItem? item) private async Task FreeTreeItem(TreeItem? item)
{ {
await this.InvokeAsync(() => item?.Free()); await this.InvokeAsync(() => item?.Free());