From a62468123eca4ee030a2d0b12ed7bcbfd821187a Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Mon, 20 Oct 2025 20:15:45 +1000 Subject: [PATCH] add new file and dir to project --- .../IdeFileExternalChangeHandler.cs | 10 ++++---- .../FileWatching/IdeFileOperationsService.cs | 6 ++--- .../SharpIdeSolutionModificationService.cs | 4 ++-- .../SolutionDiscovery/SharpIdeFolder.cs | 1 + .../VsPersistence/SharpIdeModels.cs | 2 ++ .../Dialogs/NewDirectoryDialog.cs | 4 ++-- .../ContextMenus/FolderContextMenu.cs | 3 ++- .../ContextMenus/ProjectContextMenu.cs | 24 +++++++++++++++---- 8 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileExternalChangeHandler.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileExternalChangeHandler.cs index 2c300b8..a83dd12 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileExternalChangeHandler.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileExternalChangeHandler.cs @@ -39,14 +39,14 @@ public class IdeFileExternalChangeHandler return; } var containingFolderPath = Path.GetDirectoryName(folderPath)!; - var containingFolder = SolutionModel.AllFolders.SingleOrDefault(f => f.Path == containingFolderPath); - if (containingFolder is null) + var containingFolderOrProject = (IFolderOrProject?)SolutionModel.AllFolders.SingleOrDefault(f => f.ChildNodeBasePath == containingFolderPath) ?? SolutionModel.AllProjects.SingleOrDefault(s => s.ChildNodeBasePath == containingFolderPath); + if (containingFolderOrProject is null) { - Console.WriteLine($"Error - Containing Folder of {folderPath} does not exist"); + Console.WriteLine($"Error - Containing Folder or Project of {folderPath} does not exist"); return; } var folderName = Path.GetFileName(folderPath); - await _sharpIdeSolutionModificationService.AddDirectory(containingFolder, folderName); + await _sharpIdeSolutionModificationService.AddDirectory(containingFolderOrProject, folderName); } private async Task OnFileCreated(string filePath) @@ -61,7 +61,7 @@ public class IdeFileExternalChangeHandler // If sharpIdeFile is null, it means the file was created externally, and we need to create it and add it to the solution model var createdFileDirectory = Path.GetDirectoryName(filePath)!; - var containingFolderOrProject = (IFolderOrProject?)SolutionModel.AllFolders.SingleOrDefault(f => f.Path == createdFileDirectory) ?? SolutionModel.AllProjects.SingleOrDefault(s => s.FilePath == createdFileDirectory); + var containingFolderOrProject = (IFolderOrProject?)SolutionModel.AllFolders.SingleOrDefault(f => f.ChildNodeBasePath == createdFileDirectory) ?? SolutionModel.AllProjects.SingleOrDefault(s => s.ChildNodeBasePath == createdFileDirectory); if (containingFolderOrProject is null) { Console.WriteLine($"Error - Containing Folder or Project of {filePath} does not exist"); diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs index 6926d13..7d0bc14 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs @@ -7,11 +7,11 @@ public class IdeFileOperationsService(SharpIdeSolutionModificationService sharpI { private readonly SharpIdeSolutionModificationService _sharpIdeSolutionModificationService = sharpIdeSolutionModificationService; - public async Task CreateDirectory(SharpIdeFolder parentFolder, string newDirectoryName) + public async Task CreateDirectory(IFolderOrProject parentNode, string newDirectoryName) { - var newDirectoryPath = Path.Combine(parentFolder.Path, newDirectoryName); + var newDirectoryPath = Path.Combine(parentNode.ChildNodeBasePath, newDirectoryName); Directory.CreateDirectory(newDirectoryPath); - var newFolder = await _sharpIdeSolutionModificationService.AddDirectory(parentFolder, newDirectoryName); + var newFolder = await _sharpIdeSolutionModificationService.AddDirectory(parentNode, newDirectoryName); } public async Task DeleteDirectory(SharpIdeFolder folder) diff --git a/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs b/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs index b67e5a2..bab7f07 100644 --- a/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs +++ b/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs @@ -13,9 +13,9 @@ public class SharpIdeSolutionModificationService(FileChangedService fileChangedS public SharpIdeSolutionModel SolutionModel { get; set; } = null!; /// The directory must already exist on disk - public async Task AddDirectory(SharpIdeFolder parentFolder, string directoryName) + public async Task AddDirectory(IFolderOrProject parentFolder, string directoryName) { - var addedDirectoryPath = Path.Combine(parentFolder.Path, directoryName); + var addedDirectoryPath = Path.Combine(parentFolder.ChildNodeBasePath, directoryName); var allFiles = new ConcurrentBag(); var allFolders = new ConcurrentBag(); var sharpIdeFolder = new SharpIdeFolder(new DirectoryInfo(addedDirectoryPath), parentFolder, allFiles, allFolders); diff --git a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs index 5369eee..0373761 100644 --- a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs +++ b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs @@ -9,6 +9,7 @@ public class SharpIdeFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildShar { public required IExpandableSharpIdeNode Parent { get; set; } public required string Path { get; set; } + public string ChildNodeBasePath => Path; public required string Name { get; set; } public ObservableHashSet Files { get; init; } public ObservableHashSet Folders { get; init; } diff --git a/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs b/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs index 8a0096e..08a144c 100644 --- a/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs +++ b/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs @@ -20,6 +20,7 @@ public interface IFolderOrProject : IExpandableSharpIdeNode, IChildSharpIdeNode public ObservableHashSet Folders { get; init; } public ObservableHashSet Files { get; init; } public string Name { get; set; } + public string ChildNodeBasePath { get; } } public interface IChildSharpIdeNode { @@ -89,6 +90,7 @@ public class SharpIdeProjectModel : ISharpIdeNode, IExpandableSharpIdeNode, IChi { public required string Name { get; set; } public required string FilePath { get; set; } + public string ChildNodeBasePath => Path.GetDirectoryName(FilePath)!; public required ObservableHashSet Folders { get; init; } public required ObservableHashSet Files { get; init; } public bool Expanded { get; set; } diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/Dialogs/NewDirectoryDialog.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/Dialogs/NewDirectoryDialog.cs index 2ac93e3..78caa1a 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/Dialogs/NewDirectoryDialog.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/Dialogs/NewDirectoryDialog.cs @@ -1,6 +1,6 @@ using Godot; using SharpIDE.Application.Features.FileWatching; -using SharpIDE.Application.Features.SolutionDiscovery; +using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence; namespace SharpIDE.Godot.Features.SolutionExplorer.ContextMenus.Dialogs; @@ -8,7 +8,7 @@ public partial class NewDirectoryDialog : ConfirmationDialog { private LineEdit _nameLineEdit = null!; - public SharpIdeFolder ParentFolder { get; set; } = null!; + public IFolderOrProject ParentFolder { get; set; } = null!; [Inject] private readonly IdeFileOperationsService _ideFileOperationsService = null!; diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs index 3ef4d2d..85b6f68 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs @@ -1,6 +1,7 @@ using Godot; using SharpIDE.Application.Features.FileWatching; using SharpIDE.Application.Features.SolutionDiscovery; +using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence; using SharpIDE.Godot.Features.SolutionExplorer.ContextMenus.Dialogs; namespace SharpIDE.Godot.Features.SolutionExplorer; @@ -76,7 +77,7 @@ public partial class SolutionExplorerPanel private readonly PackedScene _newDirectoryDialogScene = GD.Load("uid://bgi4u18y8pt4x"); private readonly PackedScene _newCsharpFileDialogScene = GD.Load("uid://chnb7gmcdg0ww"); - private void OnCreateNewSubmenuPressed(long id, SharpIdeFolder folder) + private void OnCreateNewSubmenuPressed(long id, IFolderOrProject folder) { var actionId = (CreateNewSubmenuOptions)id; if (actionId is CreateNewSubmenuOptions.Directory) diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs index c3c92fe..bd01cfb 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/ProjectContextMenu.cs @@ -11,11 +11,18 @@ namespace SharpIDE.Godot.Features.SolutionExplorer; file enum ProjectContextMenuOptions { - Run = 0, - Build = 1, - Rebuild = 2, - Clean = 3, - Restore = 4 + CreateNew = 0, + Run = 1, + Build = 2, + Rebuild = 3, + Clean = 4, + Restore = 5 +} + +file enum CreateNewSubmenuOptions +{ + Directory = 1, + CSharpFile = 2 } public partial class SolutionExplorerPanel @@ -29,6 +36,13 @@ public partial class SolutionExplorerPanel { var menu = new PopupMenu(); AddChild(menu); + var createNewSubmenu = new PopupMenu(); + menu.AddSubmenuNodeItem("Add", createNewSubmenu, (int)ProjectContextMenuOptions.CreateNew); + menu.AddSeparator(); + createNewSubmenu.AddItem("Directory", (int)CreateNewSubmenuOptions.Directory); + createNewSubmenu.AddItem("C# File", (int)CreateNewSubmenuOptions.CSharpFile); + createNewSubmenu.IdPressed += id => OnCreateNewSubmenuPressed(id, project); + menu.AddIconItem(_runIcon, "Run", (int)ProjectContextMenuOptions.Run); menu.SetItemIconMaxWidth((int)ProjectContextMenuOptions.Run, 20); menu.AddSeparator();