Start adding project panel context menu actions

Antonio Scandurra created

Change summary

crates/project_panel/src/project_panel.rs | 61 +++++++++++++++++++++---
crates/workspace/src/workspace.rs         | 25 +++++++++
2 files changed, 76 insertions(+), 10 deletions(-)

Detailed changes

crates/project_panel/src/project_panel.rs 🔗

@@ -115,6 +115,10 @@ pub fn init(cx: &mut MutableAppContext) {
     cx.add_async_action(ProjectPanel::delete);
     cx.add_async_action(ProjectPanel::confirm);
     cx.add_action(ProjectPanel::cancel);
+    cx.add_action(ProjectPanel::copy);
+    cx.add_action(ProjectPanel::copy_path);
+    cx.add_action(ProjectPanel::cut);
+    cx.add_action(ProjectPanel::paste);
 }
 
 pub enum Event {
@@ -212,22 +216,47 @@ impl ProjectPanel {
 
     fn deploy_context_menu(&mut self, action: &DeployContextMenu, cx: &mut ViewContext<Self>) {
         let mut menu_entries = Vec::new();
-        menu_entries.push(ContextMenuItem::item("New File", AddFile));
-        menu_entries.push(ContextMenuItem::item("New Directory", AddDirectory));
+
         if let Some(entry_id) = action.entry_id {
             if let Some(worktree_id) = self.project.read(cx).worktree_id_for_entry(entry_id, cx) {
                 self.selection = Some(Selection {
                     worktree_id,
                     entry_id,
                 });
-                menu_entries.push(ContextMenuItem::Separator);
-                menu_entries.push(ContextMenuItem::item("Copy", Copy));
-                menu_entries.push(ContextMenuItem::item("Copy Path", CopyPath));
-                menu_entries.push(ContextMenuItem::item("Cut", Cut));
-                menu_entries.push(ContextMenuItem::item("Rename", Rename));
-                menu_entries.push(ContextMenuItem::item("Delete", Delete));
+
+                if let Some((worktree, entry)) = self.selected_entry(cx) {
+                    let is_root = Some(entry) == worktree.root_entry();
+                    menu_entries.push(ContextMenuItem::item(
+                        "Add Folder to Project",
+                        workspace::AddFolderToProject,
+                    ));
+                    if is_root {
+                        menu_entries.push(ContextMenuItem::item(
+                            "Remove Folder from Project",
+                            workspace::RemoveFolderFromProject(worktree_id),
+                        ));
+                    }
+                    menu_entries.push(ContextMenuItem::item("New File", AddFile));
+                    menu_entries.push(ContextMenuItem::item("New Folder", AddDirectory));
+                    menu_entries.push(ContextMenuItem::Separator);
+                    menu_entries.push(ContextMenuItem::item("Copy", Copy));
+                    menu_entries.push(ContextMenuItem::item("Copy Path", CopyPath));
+                    menu_entries.push(ContextMenuItem::item("Cut", Cut));
+                    menu_entries.push(ContextMenuItem::Separator);
+                    menu_entries.push(ContextMenuItem::item("Rename", Rename));
+                    if !is_root {
+                        menu_entries.push(ContextMenuItem::item("Delete", Delete));
+                    }
+                }
             }
+        } else {
+            self.selection.take();
+            menu_entries.push(ContextMenuItem::item(
+                "Add Folder to Project",
+                workspace::AddFolderToProject,
+            ));
         }
+
         self.context_menu.update(cx, |menu, cx| {
             menu.show(action.position, menu_entries, cx);
         });
@@ -581,6 +610,22 @@ impl ProjectPanel {
         }
     }
 
+    fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
+        todo!()
+    }
+
+    fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
+        todo!()
+    }
+
+    fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
+        todo!()
+    }
+
+    fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
+        todo!()
+    }
+
     fn index_for_selection(&self, selection: Selection) -> Option<(usize, usize, usize)> {
         let mut worktree_index = 0;
         let mut entry_index = 0;

crates/workspace/src/workspace.rs 🔗

@@ -30,7 +30,7 @@ use log::error;
 pub use pane::*;
 pub use pane_group::*;
 use postage::prelude::Stream;
-use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, Worktree};
+use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
 use settings::Settings;
 use sidebar::{Side, Sidebar, SidebarButtons, ToggleSidebarItem, ToggleSidebarItemFocus};
 use smallvec::SmallVec;
@@ -72,6 +72,9 @@ type FollowableItemBuilders = HashMap<
     ),
 >;
 
+#[derive(Clone)]
+pub struct RemoveFolderFromProject(pub WorktreeId);
+
 actions!(
     workspace,
     [
@@ -104,7 +107,15 @@ pub struct JoinProject {
     pub project_index: usize,
 }
 
-impl_internal_actions!(workspace, [OpenPaths, ToggleFollow, JoinProject]);
+impl_internal_actions!(
+    workspace,
+    [
+        OpenPaths,
+        ToggleFollow,
+        JoinProject,
+        RemoveFolderFromProject
+    ]
+);
 
 pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
     pane::init(cx);
@@ -148,6 +159,7 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
     cx.add_async_action(Workspace::close);
     cx.add_async_action(Workspace::save_all);
     cx.add_action(Workspace::add_folder_to_project);
+    cx.add_action(Workspace::remove_folder_from_project);
     cx.add_action(
         |workspace: &mut Workspace, _: &Unfollow, cx: &mut ViewContext<Workspace>| {
             let pane = workspace.active_pane().clone();
@@ -1028,6 +1040,15 @@ impl Workspace {
         .detach();
     }
 
+    fn remove_folder_from_project(
+        &mut self,
+        RemoveFolderFromProject(worktree_id): &RemoveFolderFromProject,
+        cx: &mut ViewContext<Self>,
+    ) {
+        self.project
+            .update(cx, |project, cx| project.remove_worktree(*worktree_id, cx));
+    }
+
     fn project_path_for_path(
         &self,
         abs_path: &Path,