diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index 9b9a24b03f099d675cb35c440ff8b8afd98985ce..121d44a877323d2285556d05f3e36bd85ef06eb9 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -1484,7 +1484,7 @@ impl Sidebar { let workspace_for_add = workspace.clone(); let multi_workspace_for_add = multi_workspace.clone(); - menu.separator().entry( + let menu = menu.separator().entry( "Add Folder to Project", Some(Box::new(AddFolderToProject)), move |window, cx| { @@ -1497,7 +1497,37 @@ impl Sidebar { workspace.add_folder_to_project(&AddFolderToProject, window, cx); }); }, - ) + ); + + let workspace_count = multi_workspace + .upgrade() + .map_or(0, |mw| mw.read(cx).workspaces().len()); + if workspace_count > 1 { + let workspace_for_move = workspace.clone(); + let multi_workspace_for_move = multi_workspace.clone(); + menu.entry( + "Move to New Window", + Some(Box::new( + zed_actions::agents_sidebar::MoveWorkspaceToNewWindow, + )), + move |window, cx| { + if let Some(mw) = multi_workspace_for_move.upgrade() { + mw.update(cx, |multi_workspace, cx| { + if let Some(index) = multi_workspace + .workspaces() + .iter() + .position(|w| *w == workspace_for_move) + { + multi_workspace + .move_workspace_to_new_window(index, window, cx); + } + }); + } + }, + ) + } else { + menu + } }); let this = this.clone(); diff --git a/crates/workspace/src/multi_workspace.rs b/crates/workspace/src/multi_workspace.rs index 6e4b99ebbfe952d1e3faf3266b80ba5cd18aff34..c89c587dd3c40b1a947bc4696326217fec065d76 100644 --- a/crates/workspace/src/multi_workspace.rs +++ b/crates/workspace/src/multi_workspace.rs @@ -11,8 +11,10 @@ use project::Project; use settings::Settings; use std::future::Future; use std::path::PathBuf; +use std::sync::Arc; use ui::prelude::*; use util::ResultExt; +use zed_actions::agents_sidebar::MoveWorkspaceToNewWindow; const SIDEBAR_RESIZE_HANDLE_SIZE: Pixels = px(6.0); @@ -636,9 +638,14 @@ impl MultiWorkspace { }) } - pub fn remove_workspace(&mut self, index: usize, window: &mut Window, cx: &mut Context) { + pub fn remove_workspace( + &mut self, + index: usize, + window: &mut Window, + cx: &mut Context, + ) -> Option> { if self.workspaces.len() <= 1 || index >= self.workspaces.len() { - return; + return None; } let removed_workspace = self.workspaces.remove(index); @@ -679,6 +686,49 @@ impl MultiWorkspace { )); cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged); cx.notify(); + + Some(removed_workspace) + } + + pub fn move_workspace_to_new_window( + &mut self, + index: usize, + window: &mut Window, + cx: &mut Context, + ) { + if self.workspaces.len() <= 1 || index >= self.workspaces.len() { + return; + } + + let Some(workspace) = self.remove_workspace(index, window, cx) else { + return; + }; + + let app_state: Arc = workspace.read(cx).app_state().clone(); + + cx.defer(move |cx| { + let options = (app_state.build_window_options)(None, cx); + + let Ok(window) = cx.open_window(options, |window, cx| { + cx.new(|cx| MultiWorkspace::new(workspace, window, cx)) + }) else { + return; + }; + + let _ = window.update(cx, |_, window, _| { + window.activate_window(); + }); + }); + } + + fn move_active_workspace_to_new_window( + &mut self, + _: &MoveWorkspaceToNewWindow, + window: &mut Window, + cx: &mut Context, + ) { + let index = self.active_workspace_index; + self.move_workspace_to_new_window(index, window, cx); } pub fn open_project( @@ -799,6 +849,7 @@ impl Render for MultiWorkspace { )) .on_action(cx.listener(Self::next_workspace)) .on_action(cx.listener(Self::previous_workspace)) + .on_action(cx.listener(Self::move_active_workspace_to_new_window)) }) .when( self.sidebar_open() && self.multi_workspace_enabled(cx), diff --git a/crates/zed_actions/src/lib.rs b/crates/zed_actions/src/lib.rs index 0306854c0ad546998c122bc79aa9caf18bbace81..f64df42e050023f9f8615dc468e7c3459a4af063 100644 --- a/crates/zed_actions/src/lib.rs +++ b/crates/zed_actions/src/lib.rs @@ -786,6 +786,8 @@ pub mod agents_sidebar { [ /// Moves focus to the sidebar's search/filter editor. FocusSidebarFilter, + /// Moves the active workspace to a new window. + MoveWorkspaceToNewWindow, ] ); }