Detailed changes
@@ -847,27 +847,6 @@ impl Editor {
Self::new(EditorMode::Full, buffer, project, None, cx)
}
- pub fn find_or_create(
- workspace: &mut Workspace,
- buffer: ModelHandle<Buffer>,
- cx: &mut ViewContext<Workspace>,
- ) -> ViewHandle<Editor> {
- let project = workspace.project().clone();
-
- if let Some(item) = project::File::from_dyn(buffer.read(cx).file())
- .and_then(|file| file.project_entry_id(cx))
- .and_then(|entry_id| workspace.active_pane().read(cx).item_for_entry(entry_id))
- .and_then(|item| item.downcast())
- {
- workspace.activate_item(&item, cx);
- return item;
- }
-
- let editor = cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx));
- workspace.add_item(Box::new(editor.clone()), cx);
- editor
- }
-
pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
let mut clone = Self::new(
self.mode,
@@ -4324,8 +4303,7 @@ impl Editor {
for definition in definitions {
let range = definition.range.to_offset(definition.buffer.read(cx));
- let target_editor_handle =
- Self::find_or_create(workspace, definition.buffer, cx);
+ let target_editor_handle = workspace.open_project_item(definition.buffer, cx);
target_editor_handle.update(cx, |target_editor, cx| {
// When selecting a definition in a different buffer, disable the nav history
// to avoid creating a history entry at the previous cursor location.
@@ -5597,7 +5575,7 @@ impl Editor {
workspace.activate_next_pane(cx);
for (buffer, ranges) in new_selections_by_buffer.into_iter() {
- let editor = Self::find_or_create(workspace, buffer, cx);
+ let editor = workspace.open_project_item::<Self>(buffer, cx);
editor.update(cx, |editor, cx| {
editor.select_ranges(ranges, Some(Autoscroll::Newest), cx);
});
@@ -4,13 +4,13 @@ use gpui::{
elements::*, AppContext, Entity, ModelHandle, RenderContext, Subscription, Task, View,
ViewContext, ViewHandle,
};
-use language::{Bias, Diagnostic, File as _};
+use language::{Bias, Buffer, Diagnostic, File as _};
use project::{File, Project, ProjectPath};
use std::fmt::Write;
use std::path::PathBuf;
use text::{Point, Selection};
use util::ResultExt;
-use workspace::{Item, ItemHandle, ItemNavHistory, Settings, StatusItemView};
+use workspace::{Item, ItemHandle, ItemNavHistory, ProjectItem, Settings, StatusItemView};
impl Item for Editor {
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) {
@@ -132,6 +132,18 @@ impl Item for Editor {
}
}
+impl ProjectItem for Editor {
+ type Item = Buffer;
+
+ fn for_project_item(
+ project: ModelHandle<Project>,
+ buffer: ModelHandle<Buffer>,
+ cx: &mut ViewContext<Self>,
+ ) -> Self {
+ Self::for_buffer(buffer, Some(project), cx)
+ }
+}
+
pub struct CursorPosition {
position: Option<Point>,
selected_count: usize,
@@ -49,6 +49,10 @@ use util::{post_inc, ResultExt, TryFutureExt as _};
pub use fs::*;
pub use worktree::*;
+pub trait Item: Entity {
+ fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId>;
+}
+
pub struct Project {
worktrees: Vec<WorktreeHandle>,
active_entry: Option<ProjectEntryId>,
@@ -4522,6 +4526,12 @@ fn relativize_path(base: &Path, path: &Path) -> PathBuf {
components.iter().map(|c| c.as_os_str()).collect()
}
+impl Item for Buffer {
+ fn entry_id(&self, cx: &AppContext) -> Option<ProjectEntryId> {
+ File::from_dyn(self.file()).and_then(|file| file.project_entry_id(cx))
+ }
+}
+
#[cfg(test)]
mod tests {
use super::{Event, *};
@@ -354,7 +354,7 @@ impl ProjectSymbolsView {
.read(cx)
.clip_point_utf16(symbol.range.start, Bias::Left);
- let editor = Editor::find_or_create(workspace, buffer, cx);
+ let editor = workspace.open_project_item::<Editor>(buffer, cx);
editor.update(cx, |editor, cx| {
editor.select_ranges(
[position..position],
@@ -280,7 +280,7 @@ impl Pane {
}
}
- pub(crate) fn open_item(
+ pub fn open_item(
&mut self,
project_entry_id: ProjectEntryId,
cx: &mut ViewContext<Self>,
@@ -195,6 +195,16 @@ pub trait Item: View {
}
}
+pub trait ProjectItem: Item {
+ type Item: project::Item;
+
+ fn for_project_item(
+ project: ModelHandle<Project>,
+ item: ModelHandle<Self::Item>,
+ cx: &mut ViewContext<Self>,
+ ) -> Self;
+}
+
pub trait ItemHandle: 'static {
fn tab_content(&self, style: &theme::Tab, cx: &AppContext) -> ElementBox;
fn project_path(&self, cx: &AppContext) -> Option<ProjectPath>;
@@ -833,6 +843,31 @@ impl Workspace {
})
}
+ pub fn open_project_item<T>(
+ &mut self,
+ project_item: ModelHandle<T::Item>,
+ cx: &mut ViewContext<Self>,
+ ) -> ViewHandle<T>
+ where
+ T: ProjectItem,
+ {
+ use project::Item as _;
+
+ if let Some(item) = project_item
+ .read(cx)
+ .entry_id(cx)
+ .and_then(|entry_id| self.active_pane().read(cx).item_for_entry(entry_id))
+ .and_then(|item| item.downcast())
+ {
+ self.activate_item(&item, cx);
+ return item;
+ }
+
+ let item = cx.add_view(|cx| T::for_project_item(self.project().clone(), project_item, cx));
+ self.add_item(Box::new(item.clone()), cx);
+ item
+ }
+
pub fn activate_item(&mut self, item: &dyn ItemHandle, cx: &mut ViewContext<Self>) -> bool {
let result = self.panes.iter().find_map(|pane| {
if let Some(ix) = pane.read(cx).index_for_item(item) {