Detailed changes
@@ -15,9 +15,9 @@ use gpui::{
use language::{Bias, Buffer, Diagnostic, DiagnosticEntry, Point, Selection, SelectionGoal};
use postage::watch;
use project::{Project, ProjectPath};
-use std::{any::TypeId, cmp::Ordering, mem, ops::Range, path::PathBuf, rc::Rc, sync::Arc};
+use std::{any::TypeId, cmp::Ordering, mem, ops::Range, path::PathBuf, sync::Arc};
use util::TryFutureExt;
-use workspace::{NavHistory, Workspace};
+use workspace::{ItemNavHistory, Workspace};
action!(Deploy);
action!(OpenExcerpts);
@@ -517,7 +517,7 @@ impl workspace::Item for ProjectDiagnostics {
fn build_view(
handle: ModelHandle<Self>,
workspace: &Workspace,
- _: Rc<NavHistory>,
+ _: ItemNavHistory,
cx: &mut ViewContext<Self::View>,
) -> Self::View {
ProjectDiagnosticsEditor::new(handle, workspace.weak_handle(), workspace.settings(), cx)
@@ -41,7 +41,6 @@ use std::{
iter::{self, FromIterator},
mem,
ops::{Deref, Range, RangeInclusive, Sub},
- rc::Rc,
sync::Arc,
time::{Duration, Instant},
};
@@ -49,7 +48,7 @@ use sum_tree::Bias;
use text::rope::TextDimension;
use theme::{DiagnosticStyle, EditorStyle};
use util::post_inc;
-use workspace::{NavHistory, PathOpener, Workspace};
+use workspace::{ItemNavHistory, PathOpener, Workspace};
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
const MAX_LINE_LEN: usize = 1024;
@@ -382,7 +381,7 @@ pub struct Editor {
mode: EditorMode,
placeholder_text: Option<Arc<str>>,
highlighted_rows: Option<Range<u32>>,
- nav_history: Option<Rc<NavHistory>>,
+ nav_history: Option<ItemNavHistory>,
}
pub struct EditorSnapshot {
@@ -468,7 +467,10 @@ impl Editor {
let mut clone = Self::new(self.buffer.clone(), self.build_settings.clone(), cx);
clone.scroll_position = self.scroll_position;
clone.scroll_top_anchor = self.scroll_top_anchor.clone();
- clone.nav_history = self.nav_history.clone();
+ clone.nav_history = self
+ .nav_history
+ .as_ref()
+ .map(|nav_history| nav_history.clone(&cx.handle()));
clone
}
@@ -2476,13 +2478,10 @@ impl Editor {
}
}
- nav_history.push(
- Some(NavigationData {
- anchor: position,
- offset,
- }),
- cx,
- );
+ nav_history.push(Some(NavigationData {
+ anchor: position,
+ offset,
+ }));
}
}
@@ -4041,7 +4040,7 @@ pub fn settings_builder(
mod tests {
use super::*;
use language::LanguageConfig;
- use std::time::Instant;
+ use std::{cell::RefCell, rc::Rc, time::Instant};
use text::Point;
use unindent::Unindent;
use util::test::sample_text;
@@ -4220,22 +4219,22 @@ mod tests {
fn test_navigation_history(cx: &mut gpui::MutableAppContext) {
cx.add_window(Default::default(), |cx| {
use workspace::ItemView;
- let nav_history = Rc::new(workspace::NavHistory::default());
+ let nav_history = Rc::new(RefCell::new(workspace::NavHistory::default()));
let settings = EditorSettings::test(&cx);
let buffer = MultiBuffer::build_simple(&sample_text(30, 5, 'a'), cx);
let mut editor = build_editor(buffer.clone(), settings, cx);
- editor.nav_history = Some(nav_history.clone());
+ editor.nav_history = Some(ItemNavHistory::new(nav_history.clone(), &cx.handle()));
// Move the cursor a small distance.
// Nothing is added to the navigation history.
editor.select_display_ranges(&[DisplayPoint::new(1, 0)..DisplayPoint::new(1, 0)], cx);
editor.select_display_ranges(&[DisplayPoint::new(3, 0)..DisplayPoint::new(3, 0)], cx);
- assert!(nav_history.pop_backward().is_none());
+ assert!(nav_history.borrow_mut().pop_backward().is_none());
// Move the cursor a large distance.
// The history can jump back to the previous position.
editor.select_display_ranges(&[DisplayPoint::new(13, 0)..DisplayPoint::new(13, 3)], cx);
- let nav_entry = nav_history.pop_backward().unwrap();
+ let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
editor.navigate(nav_entry.data.unwrap(), cx);
assert_eq!(nav_entry.item_view.id(), cx.view_id());
assert_eq!(
@@ -4251,7 +4250,7 @@ mod tests {
editor.selected_display_ranges(cx),
&[DisplayPoint::new(5, 0)..DisplayPoint::new(5, 0)]
);
- assert!(nav_history.pop_backward().is_none());
+ assert!(nav_history.borrow_mut().pop_backward().is_none());
// Move the cursor a large distance via the mouse.
// The history can jump back to the previous position.
@@ -4261,7 +4260,7 @@ mod tests {
editor.selected_display_ranges(cx),
&[DisplayPoint::new(15, 0)..DisplayPoint::new(15, 0)]
);
- let nav_entry = nav_history.pop_backward().unwrap();
+ let nav_entry = nav_history.borrow_mut().pop_backward().unwrap();
editor.navigate(nav_entry.data.unwrap(), cx);
assert_eq!(nav_entry.item_view.id(), cx.view_id());
assert_eq!(
@@ -8,13 +8,14 @@ use language::{Bias, Buffer, Diagnostic};
use postage::watch;
use project::worktree::File;
use project::{Project, ProjectEntry, ProjectPath};
+use std::cell::RefCell;
use std::rc::Rc;
use std::{fmt::Write, path::PathBuf};
use text::{Point, Selection};
use util::TryFutureExt;
use workspace::{
- ItemHandle, ItemView, ItemViewHandle, NavHistory, PathOpener, Settings, StatusItemView,
- WeakItemHandle, Workspace,
+ ItemHandle, ItemNavHistory, ItemView, ItemViewHandle, NavHistory, PathOpener, Settings,
+ StatusItemView, WeakItemHandle, Workspace,
};
pub struct BufferOpener;
@@ -46,7 +47,7 @@ impl ItemHandle for BufferItemHandle {
&self,
window_id: usize,
workspace: &Workspace,
- nav_history: Rc<NavHistory>,
+ nav_history: Rc<RefCell<NavHistory>>,
cx: &mut MutableAppContext,
) -> Box<dyn ItemViewHandle> {
let buffer = cx.add_model(|cx| MultiBuffer::singleton(self.0.clone(), cx));
@@ -57,7 +58,7 @@ impl ItemHandle for BufferItemHandle {
crate::settings_builder(weak_buffer, workspace.settings()),
cx,
);
- editor.nav_history = Some(nav_history);
+ editor.nav_history = Some(ItemNavHistory::new(nav_history, &cx.handle()));
editor
}))
}
@@ -76,14 +76,16 @@ pub struct Pane {
item_views: Vec<(usize, Box<dyn ItemViewHandle>)>,
active_item_index: usize,
settings: watch::Receiver<Settings>,
- nav_history: Rc<NavHistory>,
+ nav_history: Rc<RefCell<NavHistory>>,
}
-#[derive(Default)]
-pub struct NavHistory(RefCell<NavHistoryState>);
+pub struct ItemNavHistory {
+ history: Rc<RefCell<NavHistory>>,
+ item_view: Rc<dyn WeakItemViewHandle>,
+}
#[derive(Default)]
-struct NavHistoryState {
+pub struct NavHistory {
mode: NavigationMode,
backward_stack: VecDeque<NavigationEntry>,
forward_stack: VecDeque<NavigationEntry>,
@@ -104,7 +106,7 @@ impl Default for NavigationMode {
}
pub struct NavigationEntry {
- pub item_view: Box<dyn WeakItemViewHandle>,
+ pub item_view: Rc<dyn WeakItemViewHandle>,
pub data: Option<Box<dyn Any>>,
}
@@ -148,7 +150,7 @@ impl Pane {
) -> Task<()> {
let to_load = pane.update(cx, |pane, cx| {
// Retrieve the weak item handle from the history.
- let nav_entry = pane.nav_history.pop(mode)?;
+ let nav_entry = pane.nav_history.borrow_mut().pop(mode)?;
// If the item is still present in this pane, then activate it.
if let Some(index) = nav_entry
@@ -157,9 +159,11 @@ impl Pane {
.and_then(|v| pane.index_for_item_view(v.as_ref()))
{
if let Some(item_view) = pane.active_item() {
- pane.nav_history.set_mode(mode);
+ pane.nav_history.borrow_mut().set_mode(mode);
item_view.deactivated(cx);
- pane.nav_history.set_mode(NavigationMode::Normal);
+ pane.nav_history
+ .borrow_mut()
+ .set_mode(NavigationMode::Normal);
}
pane.active_item_index = index;
@@ -174,7 +178,6 @@ impl Pane {
// project path in order to reopen it.
else {
pane.nav_history
- .0
.borrow_mut()
.project_entries_by_item
.get(&nav_entry.item_view.id())
@@ -192,9 +195,11 @@ impl Pane {
if let Some(pane) = cx.read(|cx| pane.upgrade(cx)) {
if let Some(item) = item.log_err() {
workspace.update(&mut cx, |workspace, cx| {
- pane.update(cx, |p, _| p.nav_history.set_mode(mode));
+ pane.update(cx, |p, _| p.nav_history.borrow_mut().set_mode(mode));
let item_view = workspace.open_item_in_pane(item, &pane, cx);
- pane.update(cx, |p, _| p.nav_history.set_mode(NavigationMode::Normal));
+ pane.update(cx, |p, _| {
+ p.nav_history.borrow_mut().set_mode(NavigationMode::Normal)
+ });
if let Some(data) = nav_entry.data {
item_view.navigate(data, cx);
@@ -322,7 +327,7 @@ impl Pane {
item_view.deactivated(cx);
}
- let mut nav_history = self.nav_history.0.borrow_mut();
+ let mut nav_history = self.nav_history.borrow_mut();
if let Some(entry) = item_view.project_entry(cx) {
nav_history
.project_entries_by_item
@@ -538,16 +543,36 @@ impl View for Pane {
}
}
+impl ItemNavHistory {
+ pub fn new<T: ItemView>(history: Rc<RefCell<NavHistory>>, item_view: &ViewHandle<T>) -> Self {
+ Self {
+ history,
+ item_view: Rc::new(item_view.downgrade()),
+ }
+ }
+
+ pub fn clone<T: ItemView>(&self, item_view: &ViewHandle<T>) -> Self {
+ Self {
+ history: self.history.clone(),
+ item_view: Rc::new(item_view.downgrade()),
+ }
+ }
+
+ pub fn push<D: 'static + Any>(&self, data: Option<D>) {
+ self.history.borrow_mut().push(data, self.item_view.clone());
+ }
+}
+
impl NavHistory {
- pub fn pop_backward(&self) -> Option<NavigationEntry> {
- self.0.borrow_mut().backward_stack.pop_back()
+ pub fn pop_backward(&mut self) -> Option<NavigationEntry> {
+ self.backward_stack.pop_back()
}
- pub fn pop_forward(&self) -> Option<NavigationEntry> {
- self.0.borrow_mut().forward_stack.pop_back()
+ pub fn pop_forward(&mut self) -> Option<NavigationEntry> {
+ self.forward_stack.pop_back()
}
- fn pop(&self, mode: NavigationMode) -> Option<NavigationEntry> {
+ fn pop(&mut self, mode: NavigationMode) -> Option<NavigationEntry> {
match mode {
NavigationMode::Normal => None,
NavigationMode::GoingBack => self.pop_backward(),
@@ -555,38 +580,41 @@ impl NavHistory {
}
}
- fn set_mode(&self, mode: NavigationMode) {
- self.0.borrow_mut().mode = mode;
+ fn set_mode(&mut self, mode: NavigationMode) {
+ self.mode = mode;
}
- pub fn push<D: 'static + Any, T: ItemView>(&self, data: Option<D>, cx: &mut ViewContext<T>) {
- let mut state = self.0.borrow_mut();
- match state.mode {
+ pub fn push<D: 'static + Any>(
+ &mut self,
+ data: Option<D>,
+ item_view: Rc<dyn WeakItemViewHandle>,
+ ) {
+ match self.mode {
NavigationMode::Normal => {
- if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
- state.backward_stack.pop_front();
+ if self.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
+ self.backward_stack.pop_front();
}
- state.backward_stack.push_back(NavigationEntry {
- item_view: Box::new(cx.weak_handle()),
+ self.backward_stack.push_back(NavigationEntry {
+ item_view,
data: data.map(|data| Box::new(data) as Box<dyn Any>),
});
- state.forward_stack.clear();
+ self.forward_stack.clear();
}
NavigationMode::GoingBack => {
- if state.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
- state.forward_stack.pop_front();
+ if self.forward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
+ self.forward_stack.pop_front();
}
- state.forward_stack.push_back(NavigationEntry {
- item_view: Box::new(cx.weak_handle()),
+ self.forward_stack.push_back(NavigationEntry {
+ item_view,
data: data.map(|data| Box::new(data) as Box<dyn Any>),
});
}
NavigationMode::GoingForward => {
- if state.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
- state.backward_stack.pop_front();
+ if self.backward_stack.len() >= MAX_NAVIGATION_HISTORY_LEN {
+ self.backward_stack.pop_front();
}
- state.backward_stack.push_back(NavigationEntry {
- item_view: Box::new(cx.weak_handle()),
+ self.backward_stack.push_back(NavigationEntry {
+ item_view,
data: data.map(|data| Box::new(data) as Box<dyn Any>),
});
}
@@ -34,6 +34,7 @@ use status_bar::StatusBar;
pub use status_bar::StatusItemView;
use std::{
any::{Any, TypeId},
+ cell::RefCell,
future::Future,
hash::{Hash, Hasher},
path::{Path, PathBuf},
@@ -141,7 +142,7 @@ pub trait Item: Entity + Sized {
fn build_view(
handle: ModelHandle<Self>,
workspace: &Workspace,
- nav_history: Rc<NavHistory>,
+ nav_history: ItemNavHistory,
cx: &mut ViewContext<Self::View>,
) -> Self::View;
fn project_entry(&self) -> Option<ProjectEntry>;
@@ -205,7 +206,7 @@ pub trait ItemHandle: Send + Sync {
&self,
window_id: usize,
workspace: &Workspace,
- nav_history: Rc<NavHistory>,
+ nav_history: Rc<RefCell<NavHistory>>,
cx: &mut MutableAppContext,
) -> Box<dyn ItemViewHandle>;
fn boxed_clone(&self) -> Box<dyn ItemHandle>;
@@ -258,10 +259,11 @@ impl<T: Item> ItemHandle for ModelHandle<T> {
&self,
window_id: usize,
workspace: &Workspace,
- nav_history: Rc<NavHistory>,
+ nav_history: Rc<RefCell<NavHistory>>,
cx: &mut MutableAppContext,
) -> Box<dyn ItemViewHandle> {
Box::new(cx.add_view(window_id, |cx| {
+ let nav_history = ItemNavHistory::new(nav_history, &cx.handle());
T::build_view(self.clone(), workspace, nav_history, cx)
}))
}
@@ -292,7 +294,7 @@ impl ItemHandle for Box<dyn ItemHandle> {
&self,
window_id: usize,
workspace: &Workspace,
- nav_history: Rc<NavHistory>,
+ nav_history: Rc<RefCell<NavHistory>>,
cx: &mut MutableAppContext,
) -> Box<dyn ItemViewHandle> {
ItemHandle::add_view(self.as_ref(), window_id, workspace, nav_history, cx)