diff --git a/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs b/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs index e5309c7..70b53b7 100644 --- a/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs +++ b/src/SharpIDE.Application/Features/FileWatching/IdeFileOperationsService.cs @@ -12,4 +12,10 @@ public class IdeFileOperationsService(SharpIdeSolutionModificationService sharpI Directory.CreateDirectory(newDirectoryPath); var newFolder = await _sharpIdeSolutionModificationService.AddDirectory(parentFolder, newDirectoryName); } + + public async Task DeleteDirectory(SharpIdeFolder folder) + { + Directory.Delete(folder.Path, true); + await _sharpIdeSolutionModificationService.RemoveDirectory(folder); + } } diff --git a/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs b/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs index 9888843..ee704ce 100644 --- a/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs +++ b/src/SharpIDE.Application/Features/FileWatching/SharpIdeSolutionModificationService.cs @@ -17,4 +17,11 @@ public class SharpIdeSolutionModificationService SolutionModel.AllFolders.Add(sharpIdeFolder); return sharpIdeFolder; } + + public async Task RemoveDirectory(SharpIdeFolder folder) + { + var parentFolderOrProject = (IFolderOrProject)folder.Parent; + parentFolderOrProject.Folders.Remove(folder); + SolutionModel.AllFolders.Remove(folder); + } } diff --git a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs index bea82a8..5369eee 100644 --- a/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs +++ b/src/SharpIDE.Application/Features/SolutionDiscovery/SharpIdeFolder.cs @@ -5,7 +5,7 @@ using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence; namespace SharpIDE.Application.Features.SolutionDiscovery; -public class SharpIdeFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode +public class SharpIdeFolder : ISharpIdeNode, IExpandableSharpIdeNode, IChildSharpIdeNode, IFolderOrProject { public required IExpandableSharpIdeNode Parent { get; set; } public required string Path { get; set; } diff --git a/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs b/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs index 5207188..de4b3d8 100644 --- a/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs +++ b/src/SharpIDE.Application/Features/SolutionDiscovery/VsPersistence/SharpIdeModels.cs @@ -14,6 +14,12 @@ public interface IExpandableSharpIdeNode { public bool Expanded { get; set; } } + +public interface IFolderOrProject +{ + public ObservableHashSet Folders { get; init; } + public ObservableHashSet Files { get; init; } +} public interface IChildSharpIdeNode { public IExpandableSharpIdeNode Parent { get; set; } diff --git a/src/SharpIDE.Godot/Features/Common/TreeItemContainer.cs b/src/SharpIDE.Godot/Features/Common/TreeItemContainer.cs index cb01708..ff9b5d7 100644 --- a/src/SharpIDE.Godot/Features/Common/TreeItemContainer.cs +++ b/src/SharpIDE.Godot/Features/Common/TreeItemContainer.cs @@ -15,7 +15,7 @@ public static class ObservableTreeExtensions { foreach (var existing in hashSet) { - var viewChangedEvent = new ViewChangedEvent(NotifyCollectionChangedAction.Add, (existing, new TreeItemContainer()), (null!, null!), 0, 0, new SortOperation()); + var viewChangedEvent = new ViewChangedEvent(NotifyCollectionChangedAction.Add, (existing, new TreeItemContainer()), (null!, null!), -1, -1, new SortOperation()); func(viewChangedEvent); } return hashSet; diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs index 81465d1..78945da 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/ContextMenus/FolderContextMenu.cs @@ -1,4 +1,5 @@ using Godot; +using SharpIDE.Application.Features.FileWatching; using SharpIDE.Application.Features.SolutionDiscovery; using SharpIDE.Godot.Features.SolutionExplorer.ContextMenus.Dialogs; @@ -7,7 +8,8 @@ namespace SharpIDE.Godot.Features.SolutionExplorer; file enum FolderContextMenuOptions { CreateNew = 1, - RevealInFileExplorer = 2 + RevealInFileExplorer = 2, + Delete = 3 } file enum CreateNewSubmenuOptions @@ -18,6 +20,7 @@ file enum CreateNewSubmenuOptions public partial class SolutionExplorerPanel { + [Inject] private readonly IdeFileOperationsService _ideFileOperationsService = null!; private void OpenContextMenuFolder(SharpIdeFolder folder) { var menu = new PopupMenu(); @@ -30,6 +33,7 @@ public partial class SolutionExplorerPanel createNewSubmenu.IdPressed += id => OnCreateNewSubmenuPressed(id, folder); menu.AddItem("Reveal in File Explorer", (int)FolderContextMenuOptions.RevealInFileExplorer); + menu.AddItem("Delete", (int)FolderContextMenuOptions.Delete); menu.PopupHide += () => menu.QueueFree(); menu.IdPressed += id => { @@ -38,6 +42,31 @@ public partial class SolutionExplorerPanel { OS.ShellOpen(folder.Path); } + else if (actionId is FolderContextMenuOptions.Delete) + { + var confirmedTcs = new TaskCompletionSource(); + var confirmationDialog = new ConfirmationDialog(); + confirmationDialog.Title = "Delete"; + confirmationDialog.DialogText = $"Delete '{folder.Name}' file?"; + confirmationDialog.Confirmed += () => + { + confirmedTcs.SetResult(true); + }; + confirmationDialog.Canceled += () => + { + confirmedTcs.SetResult(false); + }; + AddChild(confirmationDialog); + confirmationDialog.PopupCentered(); + _ = Task.GodotRun(async () => + { + var confirmed = await confirmedTcs.Task; + if (confirmed) + { + await _ideFileOperationsService.DeleteDirectory(folder); + } + }); + } }; var globalMousePosition = GetGlobalMousePosition();