Allow splitting terminal items in the central pane group (#22088)

Follow-up of https://github.com/zed-industries/zed/pull/22004
Closes https://github.com/zed-industries/zed/issues/22078

Release Notes:

- Fixed splitting terminal items in the center
This commit is contained in:
Kirill Bulatov 2024-12-16 19:23:01 +02:00 committed by GitHub
parent 88f7942f11
commit ff2ad63037
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 294 additions and 256 deletions

View file

@ -335,24 +335,13 @@ impl TerminalPanel {
self.serialize(cx);
}
pane::Event::Split(direction) => {
let new_pane = self.new_pane_with_cloned_active_terminal(cx);
let Some(new_pane) = self.new_pane_with_cloned_active_terminal(cx) else {
return;
};
let pane = pane.clone();
let direction = *direction;
cx.spawn(move |terminal_panel, mut cx| async move {
let Some(new_pane) = new_pane.await else {
return;
};
terminal_panel
.update(&mut cx, |terminal_panel, cx| {
terminal_panel
.center
.split(&pane, &new_pane, direction)
.log_err();
cx.focus_view(&new_pane);
})
.ok();
})
.detach();
self.center.split(&pane, &new_pane, direction).log_err();
cx.focus_view(&new_pane);
}
pane::Event::Focus => {
self.active_pane = pane.clone();
@ -365,63 +354,56 @@ impl TerminalPanel {
fn new_pane_with_cloned_active_terminal(
&mut self,
cx: &mut ViewContext<Self>,
) -> Task<Option<View<Pane>>> {
let Some(workspace) = self.workspace.clone().upgrade() else {
return Task::ready(None);
};
let database_id = workspace.read(cx).database_id();
) -> Option<View<Pane>> {
let workspace = self.workspace.clone().upgrade()?;
let workspace = workspace.read(cx);
let database_id = workspace.database_id();
let weak_workspace = self.workspace.clone();
let project = workspace.read(cx).project().clone();
let working_directory = self
let project = workspace.project().clone();
let (working_directory, python_venv_directory) = self
.active_pane
.read(cx)
.active_item()
.and_then(|item| item.downcast::<TerminalView>())
.and_then(|terminal_view| {
terminal_view
.read(cx)
.terminal()
.read(cx)
.working_directory()
.map(|terminal_view| {
let terminal = terminal_view.read(cx).terminal().read(cx);
(
terminal
.working_directory()
.or_else(|| default_working_directory(workspace, cx)),
terminal.python_venv_directory.clone(),
)
})
.or_else(|| default_working_directory(workspace.read(cx), cx));
.unwrap_or((None, None));
let kind = TerminalKind::Shell(working_directory);
let window = cx.window_handle();
cx.spawn(move |terminal_panel, mut cx| async move {
let terminal = project
.update(&mut cx, |project, cx| {
project.create_terminal(kind, window, cx)
})
.log_err()?
.await
.log_err()?;
let terminal_view = Box::new(
cx.new_view(|cx| {
TerminalView::new(terminal.clone(), weak_workspace.clone(), database_id, cx)
})
.ok()?,
);
let pane = terminal_panel
.update(&mut cx, |terminal_panel, cx| {
let pane = new_terminal_pane(
weak_workspace,
project,
terminal_panel.active_pane.read(cx).is_zoomed(),
cx,
);
terminal_panel.apply_tab_bar_buttons(&pane, cx);
pane
})
.ok()?;
pane.update(&mut cx, |pane, cx| {
pane.add_item(terminal_view, true, true, None, cx);
let terminal = project
.update(cx, |project, cx| {
project.create_terminal_with_venv(kind, python_venv_directory, window, cx)
})
.ok()?;
Some(pane)
})
let terminal_view = Box::new(cx.new_view(|cx| {
TerminalView::new(
terminal.clone(),
weak_workspace.clone(),
database_id,
project.downgrade(),
cx,
)
}));
let pane = new_terminal_pane(
weak_workspace,
project,
self.active_pane.read(cx).is_zoomed(),
cx,
);
self.apply_tab_bar_buttons(&pane, cx);
pane.update(cx, |pane, cx| {
pane.add_item(terminal_view, true, true, None, cx);
});
Some(pane)
}
pub fn open_terminal(
@ -724,6 +706,7 @@ impl TerminalPanel {
terminal.clone(),
workspace.weak_handle(),
workspace.database_id(),
workspace.project().downgrade(),
cx,
)
});
@ -739,17 +722,19 @@ impl TerminalPanel {
reveal_strategy: RevealStrategy,
cx: &mut ViewContext<Self>,
) -> Task<Result<Model<Terminal>>> {
if !self.is_enabled(cx) {
return Task::ready(Err(anyhow!(
"terminal not yet supported for remote projects"
)));
}
let workspace = self.workspace.clone();
self.pending_terminals_to_add += 1;
cx.spawn(|terminal_panel, mut cx| async move {
let pane = terminal_panel.update(&mut cx, |this, _| this.active_pane.clone())?;
if workspace.update(&mut cx, |workspace, cx| {
!is_enabled_in_workspace(workspace, cx)
})? {
anyhow::bail!("terminal not yet supported for remote projects");
}
let pane = terminal_panel.update(&mut cx, |terminal_panel, _| {
terminal_panel.pending_terminals_to_add += 1;
terminal_panel.active_pane.clone()
})?;
let project = workspace.update(&mut cx, |workspace, _| workspace.project().clone())?;
let window = cx.window_handle();
let terminal = project
@ -763,6 +748,7 @@ impl TerminalPanel {
terminal.clone(),
workspace.weak_handle(),
workspace.database_id(),
workspace.project().downgrade(),
cx,
)
}));
@ -1218,25 +1204,19 @@ impl Render for TerminalPanel {
if let Some(pane) = panes.get(action.0).map(|p| (*p).clone()) {
cx.focus_view(&pane);
} else {
let new_pane = terminal_panel.new_pane_with_cloned_active_terminal(cx);
cx.spawn(|terminal_panel, mut cx| async move {
if let Some(new_pane) = new_pane.await {
terminal_panel
.update(&mut cx, |terminal_panel, cx| {
terminal_panel
.center
.split(
&terminal_panel.active_pane,
&new_pane,
SplitDirection::Right,
)
.log_err();
cx.focus_view(&new_pane);
})
.ok();
}
})
.detach();
if let Some(new_pane) =
terminal_panel.new_pane_with_cloned_active_terminal(cx)
{
terminal_panel
.center
.split(
&terminal_panel.active_pane,
&new_pane,
SplitDirection::Right,
)
.log_err();
cx.focus_view(&new_pane);
}
}
}))
.on_action(cx.listener(