@@ -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<Project>,
pane: ViewHandle<Pane>,
workspace: WeakViewHandle<Workspace>,
_subscriptions: Vec<Subscription>,
@@ -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<Self>) {
- if let Some(workspace) = self.workspace.upgrade(cx) {
- let working_directory_strategy = cx
- .global::<Settings>()
- .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::<Settings>()
+ .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<Self>) {
- 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<Self>) {
+ 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"
}
@@ -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<Self>);
+ fn set_active(&mut self, active: bool, cx: &mut ViewContext<Self>);
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<Self>) {
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>) {
- 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>) {
- 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<Self>) {
- 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<dyn PanelHandle>> {
@@ -615,6 +626,10 @@ pub(crate) mod test {
unimplemented!()
}
+ fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {
+ unimplemented!()
+ }
+
fn default_size(&self, _: &WindowContext) -> f32 {
match self.position.axis() {
Axis::Horizontal => 300.,