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 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);
if (correctInsertionPosition < 0)
{
@@ -147,10 +157,25 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
throw new InvalidOperationException("File already exists in the containing folder or project");
}
parentNode.Files.Insert(correctInsertionPosition, sharpIdeFile);
SolutionModel.AllFiles.Add(sharpIdeFile);
await _fileChangedService.SharpIdeFileAdded(sharpIdeFile, contents);
return sharpIdeFile;
return correctInsertionPosition;
}
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)
@@ -180,6 +205,10 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS
var newFilePath = Path.Combine(Path.GetDirectoryName(oldPath)!, renamedFileName);
fileToRename.Name = renamedFileName;
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);
return fileToRename;
}

View File

@@ -276,6 +276,7 @@ public partial class SolutionExplorerPanel : MarginContainer
.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.Move => MoveTreeItem(_tree, innerEvent.NewItem.View, innerEvent.NewItem.Value, innerEvent.OldStartingIndex, innerEvent.NewStartingIndex),
NotifyCollectionChangedAction.Remove => FreeTreeItem(innerEvent.OldItem.View.Value),
_ => Task.CompletedTask
})).AddTo(this);
@@ -308,6 +309,29 @@ public partial class SolutionExplorerPanel : MarginContainer
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)
{