diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.Clipboard.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.Clipboard.cs index 55767a7..458d851 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.Clipboard.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.Clipboard.cs @@ -7,37 +7,54 @@ namespace SharpIDE.Godot.Features.SolutionExplorer; public partial class SolutionExplorerPanel { - private void CopySelectedNodeToSlnExplorerClipboard() + private void CopySelectedNodesToSlnExplorerClipboard() => AddSelectedNodesToSlnExplorerClipboard(ClipboardOperation.Copy); + private void CutSelectedNodeToSlnExplorerClipboard() => AddSelectedNodesToSlnExplorerClipboard(ClipboardOperation.Cut); + private void AddSelectedNodesToSlnExplorerClipboard(ClipboardOperation clipboardOperation) { - var selected = _tree.GetSelected(); - if (selected is null) return; - var genericMetadata = selected.GetMetadata(0).As(); - if (genericMetadata is RefCountedContainer fileContainer) - { - _itemOnClipboard = (fileContainer.Item, ClipboardOperation.Copy); - } + var selectedItems = GetSelectedTreeItems(); + if (selectedItems.Count is 0) return; + _itemsOnClipboard = (selectedItems + .Select(item => item.GetMetadata(0).As()) + .OfType>() + .Select(s => s.Item) + .ToList(), + ClipboardOperation.Copy); } - private void CutSelectedNodeToSlnExplorerClipboard() + private List GetSelectedTreeItems() { - var selected = _tree.GetSelected(); - if (selected is null) return; - var genericMetadata = selected.GetMetadata(0).As(); - if (genericMetadata is RefCountedContainer fileContainer) + var selectedItems = new List(); + var currentItem = _tree.GetNextSelected(null); + while (currentItem != null) { - _itemOnClipboard = (fileContainer.Item, ClipboardOperation.Cut); + selectedItems.Add(currentItem); + currentItem = _tree.GetNextSelected(currentItem); } + return selectedItems; + } + + private bool HasMultipleNodesSelected() + { + var selectedCount = 0; + var currentItem = _tree.GetNextSelected(null); + while (currentItem != null) + { + selectedCount++; + if (selectedCount > 1) return true; + currentItem = _tree.GetNextSelected(currentItem); + } + return false; } private void ClearSlnExplorerClipboard() { - _itemOnClipboard = null; + _itemsOnClipboard = null; } private void CopyNodeFromClipboardToSelectedNode() { var selected = _tree.GetSelected(); - if (selected is null || _itemOnClipboard is null) return; + if (selected is null || _itemsOnClipboard is null) return; var genericMetadata = selected.GetMetadata(0).As(); IFolderOrProject? folderOrProject = genericMetadata switch { @@ -47,13 +64,16 @@ public partial class SolutionExplorerPanel }; if (folderOrProject is null) return; - var (fileToPaste, operation) = _itemOnClipboard.Value; - _itemOnClipboard = null; + var (filesToPaste, operation) = _itemsOnClipboard.Value; + _itemsOnClipboard = null; _ = Task.GodotRun(async () => { if (operation is ClipboardOperation.Copy) { - await _ideFileOperationsService.CopyFile(folderOrProject, fileToPaste.Path, fileToPaste.Name); + foreach (var fileToPaste in filesToPaste) + { + await _ideFileOperationsService.CopyFile(folderOrProject, fileToPaste.Path, fileToPaste.Name); + } } }); } diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs index 4c4c14a..f4d5f3d 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.cs @@ -28,7 +28,8 @@ public partial class SolutionExplorerPanel : MarginContainer private Tree _tree = null!; private TreeItem _rootItem = null!; private enum ClipboardOperation { Cut, Copy } - private (SharpIdeFile, ClipboardOperation)? _itemOnClipboard; + + private (List, ClipboardOperation)? _itemsOnClipboard; public override void _Ready() { _tree = GetNode("Tree"); @@ -41,7 +42,7 @@ public partial class SolutionExplorerPanel : MarginContainer // Copy if (@event is InputEventKey { Pressed: true, Keycode: Key.C, CtrlPressed: true }) { - CopySelectedNodeToSlnExplorerClipboard(); + CopySelectedNodesToSlnExplorerClipboard(); } // Cut else if (@event is InputEventKey { Pressed: true, Keycode: Key.X, CtrlPressed: true }) @@ -53,12 +54,21 @@ public partial class SolutionExplorerPanel : MarginContainer { CopyNodeFromClipboardToSelectedNode(); } + else if (@event is InputEventKey { Pressed: true, Keycode: Key.Delete }) + { + // TODO: DeleteSelectedNodes(); + } + else if (@event is InputEventKey { Pressed: true, Keycode: Key.Escape }) + { + ClearSlnExplorerClipboard(); + } } private void TreeOnItemMouseSelected(Vector2 mousePosition, long mouseButtonIndex) { var selected = _tree.GetSelected(); if (selected is null) return; + if (HasMultipleNodesSelected()) return; var mouseButtonMask = (MouseButtonMask)mouseButtonIndex; diff --git a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.tscn b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.tscn index 9d57e74..0a9f8f4 100644 --- a/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.tscn +++ b/src/SharpIDE.Godot/Features/SolutionExplorer/SolutionExplorerPanel.tscn @@ -27,3 +27,4 @@ theme_override_constants/v_separation = 1 theme_override_constants/inner_item_margin_left = 2 theme_override_constants/draw_guides = 0 allow_rmb_select = true +select_mode = 2