Detailed changes
@@ -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<gpui::Entity<Workspace>> = match &multi_workspace {
- Some(mw) => mw.read(cx).workspaces().collect::<Vec<_>>(),
- 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);
+ });
+ }
}
}
@@ -582,7 +582,7 @@ impl MultiWorkspace {
pub fn replace(
&mut self,
workspace: Entity<Workspace>,
- window: &Window,
+ window: &mut Window,
cx: &mut Context<Self>,
) {
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<Workspace>, cx: &mut Context<Self>) {
+ self.project_groups.clear();
+ self.project_groups
+ .push(ProjectGroup::from_workspace(workspace.clone(), cx));
self.active_workspace = workspace;
cx.emit(MultiWorkspaceEvent::ActiveWorkspaceChanged);
cx.notify();
@@ -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| {
@@ -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);