From e49281699c690897e7c96d8e7c6253b51259c717 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 19 May 2023 16:07:47 +0200 Subject: [PATCH] Add new terminal when the terminal panel is activated, and not on focus --- crates/project_panel/src/project_panel.rs | 2 + crates/terminal_view/src/terminal_panel.rs | 61 ++++++++++++---------- crates/workspace/src/dock.rs | 33 ++++++++---- 3 files changed, 58 insertions(+), 38 deletions(-) diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a89d544074..3476a6a155 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1401,6 +1401,8 @@ impl workspace::dock::Panel for ProjectPanel { fn set_zoomed(&mut self, _: bool, _: &mut ViewContext) {} + fn set_active(&mut self, _: bool, _: &mut ViewContext) {} + fn icon_path(&self) -> &'static str { "icons/folder_tree_16.svg" } diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 4926a8775e..4652b58072 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -1,9 +1,8 @@ use crate::TerminalView; use gpui::{ - actions, elements::*, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, - ViewHandle, WeakViewHandle, WindowContext, + actions, anyhow, elements::*, AppContext, Entity, Subscription, View, ViewContext, ViewHandle, + WeakViewHandle, WindowContext, }; -use project::Project; use settings::{settings_file::SettingsFile, Settings, TerminalDockPosition, WorkingDirectory}; use util::ResultExt; use workspace::{ @@ -26,7 +25,6 @@ pub enum Event { } pub struct TerminalPanel { - project: ModelHandle, pane: ViewHandle, workspace: WeakViewHandle, _subscriptions: Vec, @@ -86,7 +84,6 @@ impl TerminalPanel { cx.subscribe(&pane, Self::handle_pane_event), ]; Self { - project: workspace.project().clone(), pane, workspace: workspace.weak_handle(), _subscriptions: subscriptions, @@ -109,30 +106,34 @@ impl TerminalPanel { } fn add_terminal(&mut self, _: &workspace::NewTerminal, cx: &mut ViewContext) { - if let Some(workspace) = self.workspace.upgrade(cx) { - let working_directory_strategy = cx - .global::() - .terminal_overrides - .working_directory - .clone() - .unwrap_or(WorkingDirectory::CurrentProjectDirectory); - let working_directory = - crate::get_working_directory(workspace.read(cx), cx, working_directory_strategy); - let window_id = cx.window_id(); - if let Some(terminal) = self.project.update(cx, |project, cx| { - project - .create_terminal(working_directory, window_id, cx) - .log_err() - }) { - workspace.update(cx, |workspace, cx| { + let workspace = self.workspace.clone(); + cx.spawn(|this, mut cx| async move { + let pane = this.read_with(&cx, |this, _| this.pane.clone())?; + workspace.update(&mut cx, |workspace, cx| { + let working_directory_strategy = cx + .global::() + .terminal_overrides + .working_directory + .clone() + .unwrap_or(WorkingDirectory::CurrentProjectDirectory); + let working_directory = + crate::get_working_directory(workspace, cx, working_directory_strategy); + let window_id = cx.window_id(); + if let Some(terminal) = workspace.project().update(cx, |project, cx| { + project + .create_terminal(working_directory, window_id, cx) + .log_err() + }) { let terminal = Box::new(cx.add_view(|cx| { TerminalView::new(terminal, workspace.database_id(), cx) })); - Pane::add_item(workspace, &self.pane, terminal, true, true, None, cx); - }); - } - } + Pane::add_item(workspace, &pane, terminal, true, true, None, cx); + } + })?; + anyhow::Ok(()) + }) + .detach_and_log_err(cx); } } @@ -150,10 +151,6 @@ impl View for TerminalPanel { } fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext) { - if self.pane.read(cx).items_len() == 0 { - self.add_terminal(&Default::default(), cx) - } - if cx.is_self_focused() { cx.focus(&self.pane); } @@ -215,6 +212,12 @@ impl Panel for TerminalPanel { self.pane.update(cx, |pane, cx| pane.set_zoomed(zoomed, cx)); } + fn set_active(&mut self, active: bool, cx: &mut ViewContext) { + if active && self.pane.read(cx).items_len() == 0 { + self.add_terminal(&Default::default(), cx) + } + } + fn icon_path(&self) -> &'static str { "icons/terminal_12.svg" } diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index e115e1d573..83bb54d3be 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -24,6 +24,7 @@ pub trait Panel: View { fn should_zoom_out_on_event(_: &Self::Event) -> bool; fn is_zoomed(&self, cx: &WindowContext) -> bool; fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext); + fn set_active(&mut self, active: bool, cx: &mut ViewContext); fn should_activate_on_event(_: &Self::Event) -> bool; fn should_close_on_event(_: &Self::Event) -> bool; fn has_focus(&self, cx: &WindowContext) -> bool; @@ -37,6 +38,7 @@ pub trait PanelHandle { fn set_position(&self, position: DockPosition, cx: &mut WindowContext); fn is_zoomed(&self, cx: &WindowContext) -> bool; fn set_zoomed(&self, zoomed: bool, cx: &mut WindowContext); + fn set_active(&self, active: bool, cx: &mut WindowContext); fn default_size(&self, cx: &WindowContext) -> f32; fn icon_path(&self, cx: &WindowContext) -> &'static str; fn icon_tooltip(&self, cx: &WindowContext) -> String; @@ -77,6 +79,10 @@ where self.update(cx, |this, cx| this.set_zoomed(zoomed, cx)) } + fn set_active(&self, active: bool, cx: &mut WindowContext) { + self.update(cx, |this, cx| this.set_active(active, cx)) + } + fn icon_path(&self, cx: &WindowContext) -> &'static str { self.read(cx).icon_path() } @@ -202,12 +208,16 @@ impl Dock { pub fn set_open(&mut self, open: bool, cx: &mut ViewContext) { if open != self.is_open { self.is_open = open; + if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + active_panel.panel.set_active(open, cx); + } + cx.notify(); } } pub fn toggle_open(&mut self, cx: &mut ViewContext) { - self.is_open = !self.is_open; + self.set_open(!self.is_open, cx); cx.notify(); } @@ -297,17 +307,18 @@ impl Dock { } pub fn activate_panel(&mut self, panel_ix: usize, cx: &mut ViewContext) { - self.active_panel_index = panel_ix; - cx.notify(); - } + if panel_ix != self.active_panel_index { + if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + active_panel.panel.set_active(false, cx); + } - pub fn toggle_panel(&mut self, panel_ix: usize, cx: &mut ViewContext) { - if self.active_panel_index == panel_ix { - self.is_open = false; - } else { self.active_panel_index = panel_ix; + if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + active_panel.panel.set_active(true, cx); + } + + cx.notify(); } - cx.notify(); } pub fn active_panel(&self) -> Option<&Rc> { @@ -615,6 +626,10 @@ pub(crate) mod test { unimplemented!() } + fn set_active(&mut self, _active: bool, _cx: &mut ViewContext) { + unimplemented!() + } + fn default_size(&self, _: &WindowContext) -> f32 { match self.position.axis() { Axis::Horizontal => 300.,