Rework new terminal actions

Mikayla Maki created

Change summary

crates/terminal_view/src/terminal_panel.rs | 19 +++++-
crates/terminal_view/src/terminal_view.rs  |  8 +-
crates/workspace/src/pane.rs               |  6 -
crates/workspace/src/workspace.rs          | 64 +++++++----------------
4 files changed, 41 insertions(+), 56 deletions(-)

Detailed changes

crates/terminal_view/src/terminal_panel.rs 🔗

@@ -22,7 +22,7 @@ const TERMINAL_PANEL_KEY: &'static str = "TerminalPanel";
 actions!(terminal_panel, [ToggleFocus]);
 
 pub fn init(cx: &mut AppContext) {
-    cx.add_action(TerminalPanel::add_terminal);
+    cx.add_action(TerminalPanel::new_terminal);
 }
 
 pub enum Event {
@@ -80,7 +80,7 @@ impl TerminalPanel {
                             cx.window_context().defer(move |cx| {
                                 if let Some(this) = this.upgrade(cx) {
                                     this.update(cx, |this, cx| {
-                                        this.add_terminal(&Default::default(), cx);
+                                        this.add_terminal(cx);
                                     });
                                 }
                             })
@@ -220,7 +220,18 @@ impl TerminalPanel {
         }
     }
 
-    fn add_terminal(&mut self, _: &workspace::NewTerminal, cx: &mut ViewContext<Self>) {
+
+    fn new_terminal(workspace: &mut Workspace, _: &workspace::NewTerminal, cx: &mut ViewContext<Workspace>) {
+        let Some(this) = workspace.focus_panel::<Self>(cx) else {
+            return;
+        };
+
+        this.update(cx, |this, cx| {
+            this.add_terminal(cx)
+        })
+    }
+
+    fn add_terminal(&mut self, cx: &mut ViewContext<Self>) {
         let workspace = self.workspace.clone();
         cx.spawn(|this, mut cx| async move {
             let pane = this.read_with(&cx, |this, _| this.pane.clone())?;
@@ -363,7 +374,7 @@ impl Panel for TerminalPanel {
 
     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)
+            self.add_terminal(cx)
         }
     }
 

crates/terminal_view/src/terminal_view.rs 🔗

@@ -38,7 +38,7 @@ use workspace::{
     notifications::NotifyResultExt,
     pane, register_deserializable_item,
     searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle},
-    Pane, ToolbarItemLocation, Workspace, WorkspaceId,
+    Pane, ToolbarItemLocation, Workspace, WorkspaceId, NewCenterTerminal,
 };
 
 pub use terminal::TerminalSettings;
@@ -66,10 +66,10 @@ pub fn init(cx: &mut AppContext) {
     terminal_panel::init(cx);
     terminal::init(cx);
 
-    cx.add_action(TerminalView::deploy);
-
     register_deserializable_item::<TerminalView>(cx);
 
+    cx.add_action(TerminalView::deploy);
+
     //Useful terminal views
     cx.add_action(TerminalView::send_text);
     cx.add_action(TerminalView::send_keystroke);
@@ -101,7 +101,7 @@ impl TerminalView {
     ///Create a new Terminal in the current working directory or the user's home directory
     pub fn deploy(
         workspace: &mut Workspace,
-        _: &workspace::NewTerminal,
+        _: &NewCenterTerminal,
         cx: &mut ViewContext<Workspace>,
     ) {
         let strategy = settings::get::<TerminalSettings>(cx);

crates/workspace/src/pane.rs 🔗

@@ -3,7 +3,7 @@ mod dragged_item_receiver;
 use super::{ItemHandle, SplitDirection};
 use crate::{
     item::WeakItemHandle, toolbar::Toolbar, AutosaveSetting, Item, NewFile, NewSearch, NewTerminal,
-    ToggleZoom, Workspace, WorkspaceSettings,
+    ToggleZoom, Workspace, WorkspaceSettings, NewCenterTerminal,
 };
 use anyhow::Result;
 use collections::{HashMap, HashSet, VecDeque};
@@ -131,7 +131,6 @@ pub enum Event {
 pub struct Pane {
     items: Vec<Box<dyn ItemHandle>>,
     activation_history: Vec<usize>,
-    is_active: bool,
     zoomed: bool,
     active_item_index: usize,
     last_focused_view_by_item: HashMap<usize, AnyWeakViewHandle>,
@@ -238,7 +237,6 @@ impl Pane {
         Self {
             items: Vec::new(),
             activation_history: Vec::new(),
-            is_active: true,
             zoomed: false,
             active_item_index: 0,
             last_focused_view_by_item: Default::default(),
@@ -996,7 +994,7 @@ impl Pane {
                 AnchorCorner::TopRight,
                 vec![
                     ContextMenuItem::action("New File", NewFile),
-                    ContextMenuItem::action("New Terminal", NewTerminal),
+                    ContextMenuItem::action("New Terminal", NewCenterTerminal),
                     ContextMenuItem::action("New Search", NewSearch),
                 ],
                 cx,

crates/workspace/src/workspace.rs 🔗

@@ -55,7 +55,7 @@ use std::{
     path::{Path, PathBuf},
     str,
     sync::{atomic::AtomicUsize, Arc},
-    time::Duration,
+    time::Duration, rc::Rc,
 };
 
 use crate::{
@@ -119,6 +119,7 @@ actions!(
         ActivateNextPane,
         FollowNextCollaborator,
         NewTerminal,
+        NewCenterTerminal,
         ToggleTerminalFocus,
         NewSearch,
         Feedback,
@@ -1621,44 +1622,15 @@ impl Workspace {
         self.serialize_workspace(cx);
     }
 
-    pub fn toggle_panel(
-        &mut self,
-        position: DockPosition,
-        panel_index: usize,
-        cx: &mut ViewContext<Self>,
-    ) {
-        let dock = match position {
-            DockPosition::Left => &mut self.left_dock,
-            DockPosition::Bottom => &mut self.bottom_dock,
-            DockPosition::Right => &mut self.right_dock,
-        };
-        let active_item = dock.update(cx, move |dock, cx| {
-            if dock.is_open() && dock.active_panel_index() == panel_index {
-                dock.set_open(false, cx);
-                None
-            } else {
-                dock.set_open(true, cx);
-                dock.activate_panel(panel_index, cx);
-                dock.visible_panel().cloned()
-            }
-        });
-
-        if let Some(active_item) = active_item {
-            if active_item.has_focus(cx) {
-                cx.focus_self();
-            } else {
-                cx.focus(active_item.as_any());
-            }
-        } else {
-            cx.focus_self();
-        }
-
-        self.serialize_workspace(cx);
-
-        cx.notify();
+    pub fn focus_panel<T: Panel>(&mut self, cx: &mut ViewContext<Self>) -> Option<ViewHandle<T>> {
+        self.show_or_hide_panel::<T>(cx, |_, _| true)?.as_any().clone().downcast()
     }
 
     pub fn toggle_panel_focus<T: Panel>(&mut self, cx: &mut ViewContext<Self>) {
+        self.show_or_hide_panel::<T>(cx, |panel, cx| !panel.has_focus(cx));
+    }
+
+    fn show_or_hide_panel<T: Panel>(&mut self, cx: &mut ViewContext<Self>, show: impl Fn(&dyn PanelHandle, &mut ViewContext<Dock>) -> bool) -> Option<Rc<dyn PanelHandle>> {
         for (dock, position) in [
             self.left_dock.clone(),
             self.bottom_dock.clone(),
@@ -1676,21 +1648,24 @@ impl Workspace {
             if let Some(panel_index) = dock.read(cx).panel_index_for_type::<T>() {
                 let mut focus_center = false;
                 let mut zoom_out = false;
-                dock.update(cx, |dock, cx| {
+                let panel = dock.update(cx, |dock, cx| {
                     dock.activate_panel(panel_index, cx);
 
-                    if let Some(panel) = dock.active_panel().cloned() {
-                        if panel.has_focus(cx) {
+                    let panel = dock.active_panel().cloned();
+                    if let Some(panel) = panel.as_ref() {
+                        let should_show = show(&**panel, cx);
+                        if should_show {
+                            dock.set_open(true, cx);
+                            cx.focus(panel.as_any());
+                            zoom_out = true;
+                        } else {
                             if panel.is_zoomed(cx) {
                                 dock.set_open(false, cx);
                             }
                             focus_center = true;
-                        } else {
-                            dock.set_open(true, cx);
-                            cx.focus(panel.as_any());
-                            zoom_out = true;
                         }
                     }
+                    panel
                 });
 
                 if zoom_out {
@@ -1702,9 +1677,10 @@ impl Workspace {
 
                 self.serialize_workspace(cx);
                 cx.notify();
-                break;
+                return panel;
             }
         }
+        None
     }
 
     fn zoom_out(&mut self, cx: &mut ViewContext<Self>) {