diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index ddc53537b75e5c575992cdd85c8477216c0995ea..7d715019c364f3c2c0644b3a02d533cdb551425d 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -1,44 +1,66 @@ -use gpui::{elements::*, Entity, ModelHandle, View, ViewContext, ViewHandle, WeakViewHandle}; +use crate::TerminalView; +use gpui::{ + elements::*, AppContext, Entity, ModelHandle, Subscription, View, ViewContext, ViewHandle, + WeakViewHandle, +}; use project::Project; use settings::{Settings, WorkingDirectory}; use util::ResultExt; -use workspace::{dock::Panel, DraggedItem, Pane, Workspace}; +use workspace::{dock::Panel, pane, DraggedItem, Pane, Workspace}; -use crate::TerminalView; +pub enum Event { + Close, +} pub struct TerminalPanel { project: ModelHandle, pane: ViewHandle, workspace: WeakViewHandle, + _subscription: Subscription, } impl TerminalPanel { pub fn new(workspace: &Workspace, cx: &mut ViewContext) -> Self { + let pane = cx.add_view(|cx| { + let window_id = cx.window_id(); + let mut pane = Pane::new( + workspace.weak_handle(), + workspace.app_state().background_actions, + cx, + ); + pane.on_can_drop(move |drag_and_drop, cx| { + drag_and_drop + .currently_dragged::(window_id) + .map_or(false, |(_, item)| { + item.handle.act_as::(cx).is_some() + }) + }); + pane + }); + let subscription = cx.subscribe(&pane, Self::handle_pane_event); Self { project: workspace.project().clone(), - pane: cx.add_view(|cx| { - let window_id = cx.window_id(); - let mut pane = Pane::new( - workspace.weak_handle(), - workspace.app_state().background_actions, - cx, - ); - pane.on_can_drop(move |drag_and_drop, cx| { - drag_and_drop - .currently_dragged::(window_id) - .map_or(false, |(_, item)| { - item.handle.act_as::(cx).is_some() - }) - }); - pane - }), + pane, workspace: workspace.weak_handle(), + _subscription: subscription, + } + } + + fn handle_pane_event( + &mut self, + _pane: ViewHandle, + event: &pane::Event, + cx: &mut ViewContext, + ) { + match event { + pane::Event::Remove => cx.emit(Event::Close), + _ => {} } } } impl Entity for TerminalPanel { - type Event = (); + type Event = Event; } impl View for TerminalPanel { @@ -82,4 +104,8 @@ impl View for TerminalPanel { } } -impl Panel for TerminalPanel {} +impl Panel for TerminalPanel { + fn should_close_on_event(&self, event: &Event, _: &AppContext) -> bool { + matches!(event, Event::Close) + } +} diff --git a/crates/workspace/src/dock.rs b/crates/workspace/src/dock.rs index 70708837e692e5f59874d113a4adec4f4ec00474..3acda4429764429000b8525f9778995975d22ba2 100644 --- a/crates/workspace/src/dock.rs +++ b/crates/workspace/src/dock.rs @@ -8,7 +8,10 @@ use settings::Settings; use std::rc::Rc; pub trait Panel: View { - fn should_activate_item_on_event(&self, _: &Self::Event, _: &AppContext) -> bool { + fn should_activate_on_event(&self, _: &Self::Event, _: &AppContext) -> bool { + false + } + fn should_close_on_event(&self, _: &Self::Event, _: &AppContext) -> bool { false } fn should_show_badge(&self, _: &AppContext) -> bool { @@ -53,6 +56,10 @@ impl From<&dyn PanelHandle> for AnyViewHandle { } } +pub enum Event { + Close, +} + pub struct Dock { position: DockPosition, items: Vec, @@ -138,7 +145,7 @@ impl Dock { let subscriptions = [ cx.observe(&view, |_, _, cx| cx.notify()), cx.subscribe(&view, |this, view, event, cx| { - if view.read(cx).should_activate_item_on_event(event, cx) { + if view.read(cx).should_activate_on_event(event, cx) { if let Some(ix) = this .items .iter() @@ -146,6 +153,8 @@ impl Dock { { this.activate_item(ix, cx); } + } else if view.read(cx).should_close_on_event(event, cx) { + cx.emit(Event::Close); } }), ]; @@ -183,7 +192,7 @@ impl Dock { } impl Entity for Dock { - type Event = (); + type Event = Event; } impl View for Dock { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index ee02a97439a2823f000fa6d8ec1d3d102c011268..e79f071267e3f25f1c686605effac66c5053f419 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -461,7 +461,7 @@ pub struct Workspace { leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>, database_id: WorkspaceId, app_state: Arc, - _window_subscriptions: [Subscription; 3], + _subscriptions: Vec, _apply_leader_updates: Task>, _observe_current_user: Task>, } @@ -592,7 +592,7 @@ impl Workspace { active_call = Some((call, subscriptions)); } - let subscriptions = [ + let subscriptions = vec![ cx.observe_fullscreen(|_, _, cx| cx.notify()), cx.observe_window_activation(Self::on_window_activation_changed), cx.observe_window_bounds(move |_, mut bounds, display, cx| { @@ -612,6 +612,9 @@ impl Workspace { .spawn(DB.set_window_bounds(workspace_id, bounds, display)) .detach_and_log_err(cx); }), + Self::register_dock(&left_dock, cx), + Self::register_dock(&bottom_dock, cx), + Self::register_dock(&right_dock, cx), ]; let mut this = Workspace { @@ -640,7 +643,7 @@ impl Workspace { _observe_current_user, _apply_leader_updates, leader_updates_tx, - _window_subscriptions: subscriptions, + _subscriptions: subscriptions, }; this.project_remote_id_changed(project.read(cx).remote_id(), cx); cx.defer(|this, cx| this.update_window_title(cx)); @@ -1316,6 +1319,26 @@ impl Workspace { } } + fn register_dock(dock: &ViewHandle, cx: &mut ViewContext) -> Subscription { + cx.subscribe(dock, Self::handle_dock_event) + } + + fn handle_dock_event( + &mut self, + dock: ViewHandle, + event: &dock::Event, + cx: &mut ViewContext, + ) { + match event { + dock::Event::Close => { + dock.update(cx, |dock, cx| dock.set_open(false, cx)); + self.serialize_workspace(cx); + cx.focus_self(); + cx.notify(); + } + } + } + pub fn toggle_dock(&mut self, dock_side: DockPosition, cx: &mut ViewContext) { let dock = match dock_side { DockPosition::Left => &mut self.left_dock,