diff --git a/crates/sidebar/src/sidebar.rs b/crates/sidebar/src/sidebar.rs index dd4ff4cc19313d9431c647a68bac65f3f3d52581..adfe1c7bbeeb481ffc62b919ce475e6a16f87579 100644 --- a/crates/sidebar/src/sidebar.rs +++ b/crates/sidebar/src/sidebar.rs @@ -3727,35 +3727,50 @@ pub fn dump_workspace_info( let mut output = String::new(); let this_entity = cx.entity(); - let multi_workspace = workspace.multi_workspace().and_then(|weak| weak.upgrade()); - let workspaces: Vec> = match &multi_workspace { - Some(mw) => mw.read(cx).workspaces().collect::>(), - None => vec![this_entity.clone()], - }; - let active_workspace = multi_workspace - .as_ref() - .map(|mw| mw.read(cx).active_workspace()); - - writeln!(output, "MultiWorkspace: {} workspace(s)", workspaces.len()).ok(); - writeln!(output).ok(); + let multi_workspace = workspace + .multi_workspace() + .and_then(|weak| weak.upgrade()) + .unwrap(); + + writeln!( + output, + "MultiWorkspace: {} project group(s)", + multi_workspace.read(cx).project_groups().len() + ) + .ok(); + + let active_workspace = multi_workspace.read(cx).workspace(); + + // The action handler is already inside an update on `this_entity`, + // so we must avoid a nested read/update on that same entity. + if *active_workspace == this_entity { + dump_single_workspace(workspace, &mut output, cx); + } else { + active_workspace.read_with(cx, |ws, cx| { + dump_single_workspace(ws, &mut output, cx); + }); + } - for (index, ws) in workspaces.iter().enumerate() { - let is_active = active_workspace.as_ref() == Some(ws); - writeln!( - output, - "--- Workspace {index}{} ---", - if is_active { " (active)" } else { "" } - ) - .ok(); + for project_group in multi_workspace.read(cx).project_groups() { + writeln!(output, "Project Group: {:?}", project_group.key.path_list()).ok(); + for group_workspace in &project_group.workspaces { + let is_active = active_workspace == group_workspace; + writeln!( + output, + " Workspace{}: ", + if is_active { " (active)" } else { "" } + ) + .ok(); - // The action handler is already inside an update on `this_entity`, - // so we must avoid a nested read/update on that same entity. - if *ws == this_entity { - dump_single_workspace(workspace, &mut output, cx); - } else { - ws.read_with(cx, |ws, cx| { - dump_single_workspace(ws, &mut output, cx); - }); + // The action handler is already inside an update on `this_entity`, + // so we must avoid a nested read/update on that same entity. + if *group_workspace == this_entity { + dump_single_workspace(workspace, &mut output, cx); + } else { + group_workspace.read_with(cx, |ws, cx| { + dump_single_workspace(ws, &mut output, cx); + }); + } } } diff --git a/crates/workspace/src/multi_workspace.rs b/crates/workspace/src/multi_workspace.rs index 49c132bd7c2c7e9fcdc574b1ea78915952e44b6b..f4feb9130e3e0edd4e9c10092fa175d0c008c888 100644 --- a/crates/workspace/src/multi_workspace.rs +++ b/crates/workspace/src/multi_workspace.rs @@ -582,7 +582,7 @@ impl MultiWorkspace { pub fn replace( &mut self, workspace: Entity, - window: &Window, + window: &mut Window, cx: &mut Context, ) { if !self.multi_workspace_enabled(cx) { @@ -602,10 +602,24 @@ impl MultiWorkspace { return; } - let old_workspace = std::mem::replace(&mut self.active_workspace, workspace.clone()); - - self.detach_workspace(&old_workspace, cx); + let key = workspace.read(cx).project_group_key(cx); + if let Some(group) = self.project_groups.iter_mut().find(|g| g.key == key) { + group.workspaces.push(workspace.clone()); + } else { + let active_group_ix = self + .project_groups + .iter() + .position(|group| group.workspaces.contains(&self.active_workspace)); + if let Some(ix) = active_group_ix { + self.remove_group_at_index(ix, window, cx); + } + self.project_groups.push(ProjectGroup { + key, + workspaces: vec![workspace.clone()], + }); + }; + self.active_workspace = workspace.clone(); Self::subscribe_to_workspace(&workspace, window, cx); self.sync_sidebar_to_workspace(&workspace, cx); @@ -617,6 +631,9 @@ impl MultiWorkspace { } fn set_single_workspace(&mut self, workspace: Entity, cx: &mut Context) { + self.project_groups.clear(); + self.project_groups + .push(ProjectGroup::from_workspace(workspace.clone(), cx)); self.active_workspace = workspace; cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged); cx.notify(); diff --git a/crates/workspace/src/multi_workspace_tests.rs b/crates/workspace/src/multi_workspace_tests.rs index 3726a3c5f57a28527d5f26159ff495ac88cc0e52..b1c1e59e55a51a815ec137a0b8fb5359667f4db7 100644 --- a/crates/workspace/src/multi_workspace_tests.rs +++ b/crates/workspace/src/multi_workspace_tests.rs @@ -108,7 +108,7 @@ async fn test_replace(cx: &mut TestAppContext) { // Replace the only workspace (single-workspace case). let workspace_b = multi_workspace.update_in(cx, |mw, window, cx| { let workspace = cx.new(|cx| Workspace::test_new(project_b.clone(), window, cx)); - mw.replace(workspace.clone(), &*window, cx); + mw.replace(workspace.clone(), window, cx); workspace }); @@ -148,7 +148,7 @@ async fn test_replace(cx: &mut TestAppContext) { let workspace_d = multi_workspace.update_in(cx, |mw, window, cx| { let workspace = cx.new(|cx| Workspace::test_new(project_d.clone(), window, cx)); - mw.replace(workspace.clone(), &*window, cx); + mw.replace(workspace.clone(), window, cx); workspace }); @@ -179,7 +179,7 @@ async fn test_replace(cx: &mut TestAppContext) { // Replace with workspace_b which is already in the list — should just switch. multi_workspace.update_in(cx, |mw, window, cx| { - mw.replace(workspace_b.clone(), &*window, cx); + mw.replace(workspace_b.clone(), window, cx); }); multi_workspace.read_with(cx, |mw, _cx| { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 937e2397b48acefabb63d4015b9d65eec4c4a540..3c7c22d2ba79da500f22cfd83c4cda682ac9e8b5 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1923,7 +1923,7 @@ impl Workspace { }); match open_mode { OpenMode::Replace => { - multi_workspace.replace(workspace.clone(), &*window, cx); + multi_workspace.replace(workspace.clone(), window, cx); } OpenMode::Activate => { multi_workspace.activate(workspace.clone(), window, cx);