Use the new split pane's navigation history when cloning an item

Antonio Scandurra created

Change summary

crates/diagnostics/src/diagnostics.rs | 15 ++++-----
crates/editor/src/editor.rs           |  7 +---
crates/editor/src/items.rs            |  8 +++-
crates/find/src/project_find.rs       | 46 ++++++++++++++++++++--------
crates/workspace/src/pane.rs          |  4 ++
crates/workspace/src/workspace.rs     | 21 ++++++++++---
6 files changed, 67 insertions(+), 34 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -598,7 +598,11 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
         matches!(event, Event::Saved | Event::Dirtied | Event::TitleChanged)
     }
 
-    fn clone_on_split(&self, cx: &mut ViewContext<Self>) -> Option<Self>
+    fn clone_on_split(
+        &self,
+        nav_history: ItemNavHistory,
+        cx: &mut ViewContext<Self>,
+    ) -> Option<Self>
     where
         Self: Sized,
     {
@@ -608,13 +612,8 @@ impl workspace::ItemView for ProjectDiagnosticsEditor {
             self.settings.clone(),
             cx,
         );
-        diagnostics.editor.update(cx, |editor, cx| {
-            let nav_history = self
-                .editor
-                .read(cx)
-                .nav_history()
-                .map(|nav_history| ItemNavHistory::new(nav_history.history(), &cx.handle()));
-            editor.set_nav_history(nav_history);
+        diagnostics.editor.update(cx, |editor, _| {
+            editor.set_nav_history(Some(nav_history));
         });
         Some(diagnostics)
     }

crates/editor/src/editor.rs 🔗

@@ -834,7 +834,7 @@ impl Editor {
         Self::new(EditorMode::Full, buffer, project, settings, None, cx)
     }
 
-    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
+    pub fn clone(&self, nav_history: ItemNavHistory, cx: &mut ViewContext<Self>) -> Self {
         let mut clone = Self::new(
             self.mode,
             self.buffer.clone(),
@@ -845,10 +845,7 @@ impl Editor {
         );
         clone.scroll_position = self.scroll_position;
         clone.scroll_top_anchor = self.scroll_top_anchor.clone();
-        clone.nav_history = self
-            .nav_history
-            .as_ref()
-            .map(|nav_history| ItemNavHistory::new(nav_history.history(), &cx.handle()));
+        clone.nav_history = Some(nav_history);
         clone
     }
 

crates/editor/src/items.rs 🔗

@@ -194,11 +194,15 @@ impl ItemView for Editor {
         })
     }
 
-    fn clone_on_split(&self, cx: &mut ViewContext<Self>) -> Option<Self>
+    fn clone_on_split(
+        &self,
+        nav_history: ItemNavHistory,
+        cx: &mut ViewContext<Self>,
+    ) -> Option<Self>
     where
         Self: Sized,
     {
-        Some(self.clone(cx))
+        Some(self.clone(nav_history, cx))
     }
 
     fn deactivated(&mut self, cx: &mut ViewContext<Self>) {

crates/find/src/project_find.rs 🔗

@@ -1,14 +1,18 @@
+use crate::SearchOption;
 use editor::{Anchor, Autoscroll, Editor, MultiBuffer};
 use gpui::{
-    action, elements::*, keymap::Binding, platform::CursorStyle, ElementBox, Entity, ModelContext,
-    ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
+    action, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity,
+    ModelContext, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext,
+    ViewHandle,
 };
 use postage::watch;
 use project::{search::SearchQuery, Project};
-use std::{any::TypeId, ops::Range};
-use workspace::{Settings, Workspace};
-
-use crate::SearchOption;
+use std::{
+    any::{Any, TypeId},
+    ops::Range,
+    path::PathBuf,
+};
+use workspace::{Item, ItemNavHistory, ItemView, Settings, Workspace};
 
 action!(Deploy);
 action!(Search);
@@ -98,13 +102,13 @@ impl ProjectFind {
     }
 }
 
-impl workspace::Item for ProjectFind {
+impl Item for ProjectFind {
     type View = ProjectFindView;
 
     fn build_view(
         model: ModelHandle<Self>,
-        workspace: &workspace::Workspace,
-        nav_history: workspace::ItemNavHistory,
+        workspace: &Workspace,
+        nav_history: ItemNavHistory,
         cx: &mut gpui::ViewContext<Self::View>,
     ) -> Self::View {
         let settings = workspace.settings();
@@ -186,7 +190,7 @@ impl View for ProjectFindView {
     }
 }
 
-impl workspace::ItemView for ProjectFindView {
+impl ItemView for ProjectFindView {
     fn act_as_type(
         &self,
         type_id: TypeId,
@@ -202,6 +206,11 @@ impl workspace::ItemView for ProjectFindView {
         }
     }
 
+    fn deactivated(&mut self, cx: &mut ViewContext<Self>) {
+        self.results_editor
+            .update(cx, |editor, cx| editor.deactivated(cx));
+    }
+
     fn item_id(&self, _: &gpui::AppContext) -> usize {
         self.model.id()
     }
@@ -234,13 +243,17 @@ impl workspace::ItemView for ProjectFindView {
     fn save_as(
         &mut self,
         _: ModelHandle<Project>,
-        _: std::path::PathBuf,
+        _: PathBuf,
         _: &mut ViewContext<Self>,
     ) -> Task<anyhow::Result<()>> {
         unreachable!("save_as should not have been called")
     }
 
-    fn clone_on_split(&self, cx: &mut ViewContext<Self>) -> Option<Self>
+    fn clone_on_split(
+        &self,
+        nav_history: ItemNavHistory,
+        cx: &mut ViewContext<Self>,
+    ) -> Option<Self>
     where
         Self: Sized,
     {
@@ -251,8 +264,8 @@ impl workspace::ItemView for ProjectFindView {
                 cx,
             )
         });
-        let results_editor = self.results_editor.update(cx, |editor, cx| {
-            cx.add_view(|cx| editor.clone_on_split(cx).unwrap())
+        let results_editor = self.results_editor.update(cx, |results_editor, cx| {
+            cx.add_view(|cx| results_editor.clone(nav_history, cx))
         });
         cx.observe(&self.model, |this, _, cx| this.model_changed(true, cx))
             .detach();
@@ -269,6 +282,11 @@ impl workspace::ItemView for ProjectFindView {
         view.model_changed(false, cx);
         Some(view)
     }
+
+    fn navigate(&mut self, data: Box<dyn Any>, cx: &mut ViewContext<Self>) {
+        self.results_editor
+            .update(cx, |editor, cx| editor.navigate(data, cx));
+    }
 }
 
 impl ProjectFindView {

crates/workspace/src/pane.rs 🔗

@@ -149,6 +149,10 @@ impl Pane {
         }
     }
 
+    pub(crate) fn nav_history(&self) -> &Rc<RefCell<NavHistory>> {
+        &self.nav_history
+    }
+
     pub fn activate(&self, cx: &mut ViewContext<Self>) {
         cx.emit(Event::Activate);
     }

crates/workspace/src/workspace.rs 🔗

@@ -156,7 +156,7 @@ pub trait ItemView: View {
     fn item_id(&self, cx: &AppContext) -> usize;
     fn tab_content(&self, style: &theme::Tab, cx: &AppContext) -> ElementBox;
     fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
-    fn clone_on_split(&self, _: &mut ViewContext<Self>) -> Option<Self>
+    fn clone_on_split(&self, _: ItemNavHistory, _: &mut ViewContext<Self>) -> Option<Self>
     where
         Self: Sized,
     {
@@ -229,7 +229,11 @@ pub trait ItemViewHandle: 'static {
     fn tab_content(&self, style: &theme::Tab, cx: &AppContext) -> ElementBox;
     fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
     fn boxed_clone(&self) -> Box<dyn ItemViewHandle>;
-    fn clone_on_split(&self, cx: &mut MutableAppContext) -> Option<Box<dyn ItemViewHandle>>;
+    fn clone_on_split(
+        &self,
+        nav_history: Rc<RefCell<NavHistory>>,
+        cx: &mut MutableAppContext,
+    ) -> Option<Box<dyn ItemViewHandle>>;
     fn added_to_pane(&mut self, cx: &mut ViewContext<Pane>);
     fn deactivated(&self, cx: &mut MutableAppContext);
     fn navigate(&self, data: Box<dyn Any>, cx: &mut MutableAppContext);
@@ -373,9 +377,15 @@ impl<T: ItemView> ItemViewHandle for ViewHandle<T> {
         Box::new(self.clone())
     }
 
-    fn clone_on_split(&self, cx: &mut MutableAppContext) -> Option<Box<dyn ItemViewHandle>> {
+    fn clone_on_split(
+        &self,
+        nav_history: Rc<RefCell<NavHistory>>,
+        cx: &mut MutableAppContext,
+    ) -> Option<Box<dyn ItemViewHandle>> {
         self.update(cx, |item, cx| {
-            cx.add_option_view(|cx| item.clone_on_split(cx))
+            cx.add_option_view(|cx| {
+                item.clone_on_split(ItemNavHistory::new(nav_history, &cx.handle()), cx)
+            })
         })
         .map(|handle| Box::new(handle) as Box<dyn ItemViewHandle>)
     }
@@ -1047,7 +1057,8 @@ impl Workspace {
         let new_pane = self.add_pane(cx);
         self.activate_pane(new_pane.clone(), cx);
         if let Some(item) = pane.read(cx).active_item() {
-            if let Some(clone) = item.clone_on_split(cx.as_mut()) {
+            let nav_history = new_pane.read(cx).nav_history().clone();
+            if let Some(clone) = item.clone_on_split(nav_history, cx.as_mut()) {
                 new_pane.update(cx, |new_pane, cx| new_pane.add_item_view(clone, cx));
             }
         }