Introduced ItemEvent and to_item_events function to Item trait which converts the Item's events into a standard ItemEvent similar to how SearchableItems work.
Add breadcrumb_location and breadcrumbs functions to item trait which handles rendering of the breadcrumb elements Change breadcrumb toolbar to use these new functions rather than having hard coded breadcrumb logic Add breadcrumb support to the terminal tabs Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
parent
ab81093ef5
commit
31ecb2f7bc
8 changed files with 149 additions and 99 deletions
|
@ -1,46 +1,29 @@
|
||||||
use editor::Editor;
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*, AppContext, Entity, ModelHandle, RenderContext, Subscription, View, ViewContext,
|
elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
|
||||||
ViewHandle,
|
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use project::Project;
|
|
||||||
use search::ProjectSearchView;
|
use search::ProjectSearchView;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use workspace::{ItemHandle, ToolbarItemLocation, ToolbarItemView};
|
use workspace::{ItemEvent, ItemHandle, ToolbarItemLocation, ToolbarItemView};
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
UpdateLocation,
|
UpdateLocation,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Breadcrumbs {
|
pub struct Breadcrumbs {
|
||||||
project: ModelHandle<Project>,
|
|
||||||
active_item: Option<Box<dyn ItemHandle>>,
|
active_item: Option<Box<dyn ItemHandle>>,
|
||||||
project_search: Option<ViewHandle<ProjectSearchView>>,
|
project_search: Option<ViewHandle<ProjectSearchView>>,
|
||||||
subscriptions: Vec<Subscription>,
|
subscription: Option<Subscription>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Breadcrumbs {
|
impl Breadcrumbs {
|
||||||
pub fn new(project: ModelHandle<Project>) -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
project,
|
|
||||||
active_item: Default::default(),
|
active_item: Default::default(),
|
||||||
subscriptions: Default::default(),
|
subscription: Default::default(),
|
||||||
project_search: Default::default(),
|
project_search: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fn active_symbols(
|
|
||||||
// &self,
|
|
||||||
// theme: &SyntaxTheme,
|
|
||||||
// cx: &AppContext,
|
|
||||||
// ) -> Option<(ModelHandle<Buffer>, Vec<OutlineItem<Anchor>>)> {
|
|
||||||
// let editor = self.active_item.as_ref()?.read(cx);
|
|
||||||
// let cursor = editor.selections.newest_anchor().head();
|
|
||||||
// let multibuffer = &editor.buffer().read(cx);
|
|
||||||
// let (buffer_id, symbols) = multibuffer.symbols_containing(cursor, Some(theme), cx)?;
|
|
||||||
// let buffer = multibuffer.buffer(buffer_id)?;
|
|
||||||
// Some((buffer, symbols))
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for Breadcrumbs {
|
impl Entity for Breadcrumbs {
|
||||||
|
@ -53,42 +36,16 @@ impl View for Breadcrumbs {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||||
// let (buffer, symbols) =
|
|
||||||
// if let Some((buffer, symbols)) = self.active_symbols(&theme.editor.syntax, cx) {
|
|
||||||
// (buffer, symbols)
|
|
||||||
// } else {
|
|
||||||
// return Empty::new().boxed();
|
|
||||||
// };
|
|
||||||
// let buffer = buffer.read(cx);
|
|
||||||
// let filename = if let Some(file) = buffer.file() {
|
|
||||||
// if file.path().file_name().is_none()
|
|
||||||
// || self.project.read(cx).visible_worktrees(cx).count() > 1
|
|
||||||
// {
|
|
||||||
// file.full_path(cx).to_string_lossy().to_string()
|
|
||||||
// } else {
|
|
||||||
// file.path().to_string_lossy().to_string()
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// "untitled".to_string()
|
|
||||||
// };
|
|
||||||
|
|
||||||
let theme = cx.global::<Settings>().theme.clone();
|
let theme = cx.global::<Settings>().theme.clone();
|
||||||
if let Some(breadcrumbs) = self
|
if let Some(breadcrumbs) = self
|
||||||
.active_item
|
.active_item
|
||||||
|
.as_ref()
|
||||||
.and_then(|item| item.breadcrumbs(&theme, cx))
|
.and_then(|item| item.breadcrumbs(&theme, cx))
|
||||||
{
|
{
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
.with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
|
||||||
Label::new(" 〉 ".to_string(), theme.breadcrumbs.text.clone()).boxed()
|
Label::new(" 〉 ".to_string(), theme.breadcrumbs.text.clone()).boxed()
|
||||||
}))
|
}))
|
||||||
// .with_child(Label::new(filename, theme.breadcrumbs.text.clone()).boxed())
|
|
||||||
// .with_children(symbols.into_iter().flat_map(|symbol| {
|
|
||||||
// [
|
|
||||||
// Text::new(symbol.text, theme.breadcrumbs.text.clone())
|
|
||||||
// .with_highlights(symbol.highlight_ranges)
|
|
||||||
// .boxed(),
|
|
||||||
// ]
|
|
||||||
// }))
|
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.breadcrumbs.container)
|
.with_style(theme.breadcrumbs.container)
|
||||||
.aligned()
|
.aligned()
|
||||||
|
@ -107,39 +64,25 @@ impl ToolbarItemView for Breadcrumbs {
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> ToolbarItemLocation {
|
) -> ToolbarItemLocation {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
self.subscriptions.clear();
|
|
||||||
self.active_item = None;
|
self.active_item = None;
|
||||||
self.project_search = None;
|
self.project_search = None;
|
||||||
if let Some(item) = active_pane_item {
|
if let Some(item) = active_pane_item {
|
||||||
if let Some(editor) = item.act_as::<Editor>(cx) {
|
let this = cx.weak_handle();
|
||||||
self.subscriptions
|
self.subscription = Some(item.subscribe_to_item_events(
|
||||||
.push(cx.subscribe(&editor, |_, _, event, cx| match event {
|
cx,
|
||||||
editor::Event::BufferEdited
|
Box::new(move |event, cx| {
|
||||||
| editor::Event::TitleChanged
|
if let Some(this) = this.upgrade(cx) {
|
||||||
| editor::Event::Saved
|
if let ItemEvent::UpdateBreadcrumbs = event {
|
||||||
| editor::Event::Reparsed => cx.notify(),
|
this.update(cx, |_, cx| {
|
||||||
editor::Event::SelectionsChanged { local } if *local => cx.notify(),
|
cx.emit(Event::UpdateLocation);
|
||||||
_ => {}
|
cx.notify();
|
||||||
}));
|
});
|
||||||
self.active_item = Some(editor);
|
}
|
||||||
if let Some(project_search) = item.downcast::<ProjectSearchView>() {
|
|
||||||
self.subscriptions
|
|
||||||
.push(cx.subscribe(&project_search, |_, _, _, cx| {
|
|
||||||
cx.emit(Event::UpdateLocation);
|
|
||||||
}));
|
|
||||||
self.project_search = Some(project_search.clone());
|
|
||||||
|
|
||||||
if project_search.read(cx).has_matches() {
|
|
||||||
ToolbarItemLocation::Secondary
|
|
||||||
} else {
|
|
||||||
ToolbarItemLocation::Hidden
|
|
||||||
}
|
}
|
||||||
} else {
|
}),
|
||||||
ToolbarItemLocation::PrimaryLeft { flex: None }
|
));
|
||||||
}
|
self.active_item = Some(item.boxed_clone());
|
||||||
} else {
|
item.breadcrumb_location(cx)
|
||||||
ToolbarItemLocation::Hidden
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ToolbarItemLocation::Hidden
|
ToolbarItemLocation::Hidden
|
||||||
}
|
}
|
||||||
|
@ -151,12 +94,8 @@ impl ToolbarItemView for Breadcrumbs {
|
||||||
current_location: ToolbarItemLocation,
|
current_location: ToolbarItemLocation,
|
||||||
cx: &AppContext,
|
cx: &AppContext,
|
||||||
) -> ToolbarItemLocation {
|
) -> ToolbarItemLocation {
|
||||||
if let Some(project_search) = self.project_search.as_ref() {
|
if let Some(active_item) = self.active_item.as_ref() {
|
||||||
if project_search.read(cx).has_matches() {
|
active_item.breadcrumb_location(cx)
|
||||||
ToolbarItemLocation::Secondary
|
|
||||||
} else {
|
|
||||||
ToolbarItemLocation::Hidden
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
current_location
|
current_location
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ use util::TryFutureExt;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
|
searchable::{Direction, SearchEvent, SearchableItem, SearchableItemHandle},
|
||||||
FollowableItem, Item, ItemEvent, ItemHandle, ItemNavHistory, ProjectItem, StatusItemView,
|
FollowableItem, Item, ItemEvent, ItemHandle, ItemNavHistory, ProjectItem, StatusItemView,
|
||||||
|
ToolbarItemLocation,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
|
pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
|
||||||
|
@ -476,17 +477,71 @@ impl Item for Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_item_events(event: &Self::Event) -> Vec<workspace::ItemEvent> {
|
fn to_item_events(event: &Self::Event) -> Vec<workspace::ItemEvent> {
|
||||||
|
let mut result = Vec::new();
|
||||||
match event {
|
match event {
|
||||||
Event::Closed => vec![ItemEvent::CloseItem],
|
Event::Closed => result.push(ItemEvent::CloseItem),
|
||||||
Event::Saved | Event::DirtyChanged | Event::TitleChanged => vec![ItemEvent::UpdateTab],
|
Event::Saved | Event::TitleChanged => {
|
||||||
Event::BufferEdited => vec![ItemEvent::Edit],
|
result.push(ItemEvent::UpdateTab);
|
||||||
_ => Vec::new(),
|
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||||
|
}
|
||||||
|
Event::Reparsed => {
|
||||||
|
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||||
|
}
|
||||||
|
Event::SelectionsChanged { local } if *local => {
|
||||||
|
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||||
|
}
|
||||||
|
Event::DirtyChanged => {
|
||||||
|
result.push(ItemEvent::UpdateTab);
|
||||||
|
}
|
||||||
|
Event::BufferEdited => {
|
||||||
|
result.push(ItemEvent::Edit);
|
||||||
|
result.push(ItemEvent::UpdateBreadcrumbs);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_searchable(&self, handle: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
fn as_searchable(&self, handle: &ViewHandle<Self>) -> Option<Box<dyn SearchableItemHandle>> {
|
||||||
Some(Box::new(handle.clone()))
|
Some(Box::new(handle.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
|
ToolbarItemLocation::PrimaryLeft { flex: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
|
let cursor = self.selections.newest_anchor().head();
|
||||||
|
let multibuffer = &self.buffer().read(cx);
|
||||||
|
let (buffer_id, symbols) =
|
||||||
|
multibuffer.symbols_containing(cursor, Some(&theme.editor.syntax), cx)?;
|
||||||
|
let buffer = multibuffer.buffer(buffer_id)?;
|
||||||
|
|
||||||
|
let buffer = buffer.read(cx);
|
||||||
|
let filename = if let Some(file) = buffer.file() {
|
||||||
|
if file.path().file_name().is_none()
|
||||||
|
|| self
|
||||||
|
.project
|
||||||
|
.as_ref()
|
||||||
|
.map(|project| project.read(cx).visible_worktrees(cx).count() > 1)
|
||||||
|
.unwrap_or_default()
|
||||||
|
{
|
||||||
|
file.full_path(cx).to_string_lossy().to_string()
|
||||||
|
} else {
|
||||||
|
file.path().to_string_lossy().to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"untitled".to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut breadcrumbs = vec![Label::new(filename, theme.breadcrumbs.text.clone()).boxed()];
|
||||||
|
breadcrumbs.extend(symbols.into_iter().map(|symbol| {
|
||||||
|
Text::new(symbol.text, theme.breadcrumbs.text.clone())
|
||||||
|
.with_highlights(symbol.highlight_ranges)
|
||||||
|
.boxed()
|
||||||
|
}));
|
||||||
|
Some(breadcrumbs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectItem for Editor {
|
impl ProjectItem for Editor {
|
||||||
|
|
|
@ -189,7 +189,9 @@ impl ToolbarItemView for BufferSearchBar {
|
||||||
self.active_searchable_item.take();
|
self.active_searchable_item.take();
|
||||||
self.pending_search.take();
|
self.pending_search.take();
|
||||||
|
|
||||||
if let Some(searchable_item_handle) = item.and_then(|item| item.as_searchable(cx)) {
|
if let Some(searchable_item_handle) =
|
||||||
|
item.and_then(|item| item.to_searchable_item_handle(cx))
|
||||||
|
{
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
self.active_searchable_item_subscription =
|
self.active_searchable_item_subscription =
|
||||||
Some(searchable_item_handle.subscribe_to_search_events(
|
Some(searchable_item_handle.subscribe_to_search_events(
|
||||||
|
|
|
@ -329,11 +329,23 @@ impl Item for ProjectSearchView {
|
||||||
|
|
||||||
fn to_item_events(event: &Self::Event) -> Vec<ItemEvent> {
|
fn to_item_events(event: &Self::Event) -> Vec<ItemEvent> {
|
||||||
match event {
|
match event {
|
||||||
ViewEvent::UpdateTab => vec![ItemEvent::UpdateTab],
|
ViewEvent::UpdateTab => vec![ItemEvent::UpdateBreadcrumbs, ItemEvent::UpdateTab],
|
||||||
ViewEvent::EditorEvent(editor_event) => Editor::to_item_events(editor_event),
|
ViewEvent::EditorEvent(editor_event) => Editor::to_item_events(editor_event),
|
||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
|
if self.has_matches() {
|
||||||
|
ToolbarItemLocation::Secondary
|
||||||
|
} else {
|
||||||
|
ToolbarItemLocation::Hidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
|
self.results_editor.breadcrumbs(theme, cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectSearchView {
|
impl ProjectSearchView {
|
||||||
|
|
|
@ -83,6 +83,7 @@ const DEBUG_LINE_HEIGHT: f32 = 5.;
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
TitleChanged,
|
TitleChanged,
|
||||||
|
BreadcrumbsChanged,
|
||||||
CloseTerminal,
|
CloseTerminal,
|
||||||
Bell,
|
Bell,
|
||||||
Wakeup,
|
Wakeup,
|
||||||
|
@ -494,9 +495,11 @@ impl Terminal {
|
||||||
match event {
|
match event {
|
||||||
AlacTermEvent::Title(title) => {
|
AlacTermEvent::Title(title) => {
|
||||||
self.breadcrumb_text = title.to_string();
|
self.breadcrumb_text = title.to_string();
|
||||||
|
cx.emit(Event::BreadcrumbsChanged);
|
||||||
}
|
}
|
||||||
AlacTermEvent::ResetTitle => {
|
AlacTermEvent::ResetTitle => {
|
||||||
self.breadcrumb_text = String::new();
|
self.breadcrumb_text = String::new();
|
||||||
|
cx.emit(Event::BreadcrumbsChanged);
|
||||||
}
|
}
|
||||||
AlacTermEvent::ClipboardStore(_, data) => {
|
AlacTermEvent::ClipboardStore(_, data) => {
|
||||||
cx.write_to_clipboard(ClipboardItem::new(data.to_string()))
|
cx.write_to_clipboard(ClipboardItem::new(data.to_string()))
|
||||||
|
|
|
@ -9,7 +9,7 @@ use gpui::{
|
||||||
};
|
};
|
||||||
use util::truncate_and_trailoff;
|
use util::truncate_and_trailoff;
|
||||||
use workspace::searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle};
|
use workspace::searchable::{SearchEvent, SearchOptions, SearchableItem, SearchableItemHandle};
|
||||||
use workspace::{Item, ItemEvent, Workspace};
|
use workspace::{Item, ItemEvent, ToolbarItemLocation, Workspace};
|
||||||
|
|
||||||
use crate::TerminalSize;
|
use crate::TerminalSize;
|
||||||
use project::{LocalWorktree, Project, ProjectPath};
|
use project::{LocalWorktree, Project, ProjectPath};
|
||||||
|
@ -363,13 +363,37 @@ impl Item for TerminalContainer {
|
||||||
Some(Box::new(handle.clone()))
|
Some(Box::new(handle.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_item_events(event: &Self::Event) -> Vec<workspace::ItemEvent> {
|
fn to_item_events(event: &Self::Event) -> Vec<ItemEvent> {
|
||||||
match event {
|
match event {
|
||||||
|
Event::BreadcrumbsChanged => vec![ItemEvent::UpdateBreadcrumbs],
|
||||||
Event::TitleChanged | Event::Wakeup => vec![ItemEvent::UpdateTab],
|
Event::TitleChanged | Event::Wakeup => vec![ItemEvent::UpdateTab],
|
||||||
Event::CloseTerminal => vec![ItemEvent::CloseItem],
|
Event::CloseTerminal => vec![ItemEvent::CloseItem],
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
|
if self.connected().is_some() {
|
||||||
|
ToolbarItemLocation::PrimaryLeft { flex: None }
|
||||||
|
} else {
|
||||||
|
ToolbarItemLocation::Hidden
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
|
let connected = self.connected()?;
|
||||||
|
|
||||||
|
Some(vec![Text::new(
|
||||||
|
connected
|
||||||
|
.read(cx)
|
||||||
|
.terminal()
|
||||||
|
.read(cx)
|
||||||
|
.breadcrumb_text
|
||||||
|
.to_string(),
|
||||||
|
theme.breadcrumbs.text.clone(),
|
||||||
|
)
|
||||||
|
.boxed()])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SearchableItem for TerminalContainer {
|
impl SearchableItem for TerminalContainer {
|
||||||
|
|
|
@ -339,7 +339,7 @@ pub trait Item: View {
|
||||||
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
ToolbarItemLocation::Hidden
|
ToolbarItemLocation::Hidden
|
||||||
}
|
}
|
||||||
fn breadcrumbs(&self, _theme: &Theme) -> Option<Vec<ElementBox>> {
|
fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,6 +437,11 @@ impl<T: FollowableItem> FollowableItemHandle for ViewHandle<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ItemHandle: 'static + fmt::Debug {
|
pub trait ItemHandle: 'static + fmt::Debug {
|
||||||
|
fn subscribe_to_item_events(
|
||||||
|
&self,
|
||||||
|
cx: &mut MutableAppContext,
|
||||||
|
handler: Box<dyn Fn(ItemEvent, &mut MutableAppContext)>,
|
||||||
|
) -> gpui::Subscription;
|
||||||
fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<Cow<'a, str>>;
|
fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<Cow<'a, str>>;
|
||||||
fn tab_content(&self, detail: Option<usize>, style: &theme::Tab, cx: &AppContext)
|
fn tab_content(&self, detail: Option<usize>, style: &theme::Tab, cx: &AppContext)
|
||||||
-> ElementBox;
|
-> ElementBox;
|
||||||
|
@ -476,8 +481,7 @@ pub trait ItemHandle: 'static + fmt::Debug {
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
callback: Box<dyn FnOnce(&mut MutableAppContext)>,
|
callback: Box<dyn FnOnce(&mut MutableAppContext)>,
|
||||||
) -> gpui::Subscription;
|
) -> gpui::Subscription;
|
||||||
fn as_searchable(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
|
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
|
||||||
|
|
||||||
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
|
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
|
||||||
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<ElementBox>>;
|
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<ElementBox>>;
|
||||||
}
|
}
|
||||||
|
@ -500,6 +504,18 @@ impl dyn ItemHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Item> ItemHandle for ViewHandle<T> {
|
impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
|
fn subscribe_to_item_events(
|
||||||
|
&self,
|
||||||
|
cx: &mut MutableAppContext,
|
||||||
|
handler: Box<dyn Fn(ItemEvent, &mut MutableAppContext)>,
|
||||||
|
) -> gpui::Subscription {
|
||||||
|
cx.subscribe(self, move |_, event, cx| {
|
||||||
|
for item_event in T::to_item_events(event) {
|
||||||
|
handler(item_event, cx)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<Cow<'a, str>> {
|
fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option<Cow<'a, str>> {
|
||||||
self.read(cx).tab_description(detail, cx)
|
self.read(cx).tab_description(detail, cx)
|
||||||
}
|
}
|
||||||
|
@ -762,7 +778,7 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
cx.observe_release(self, move |_, cx| callback(cx))
|
cx.observe_release(self, move |_, cx| callback(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_searchable(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>> {
|
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>> {
|
||||||
self.read(cx).as_searchable(self)
|
self.read(cx).as_searchable(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +787,7 @@ impl<T: Item> ItemHandle for ViewHandle<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
|
||||||
self.read(cx).breadcrumbs(theme)
|
self.read(cx).breadcrumbs(theme, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,12 +225,11 @@ pub fn initialize_workspace(
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) {
|
) {
|
||||||
cx.subscribe(&cx.handle(), {
|
cx.subscribe(&cx.handle(), {
|
||||||
let project = workspace.project().clone();
|
|
||||||
move |_, _, event, cx| {
|
move |_, _, event, cx| {
|
||||||
if let workspace::Event::PaneAdded(pane) = event {
|
if let workspace::Event::PaneAdded(pane) = event {
|
||||||
pane.update(cx, |pane, cx| {
|
pane.update(cx, |pane, cx| {
|
||||||
pane.toolbar().update(cx, |toolbar, cx| {
|
pane.toolbar().update(cx, |toolbar, cx| {
|
||||||
let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(project.clone()));
|
let breadcrumbs = cx.add_view(|_| Breadcrumbs::new());
|
||||||
toolbar.add_item(breadcrumbs, cx);
|
toolbar.add_item(breadcrumbs, cx);
|
||||||
let buffer_search_bar = cx.add_view(BufferSearchBar::new);
|
let buffer_search_bar = cx.add_view(BufferSearchBar::new);
|
||||||
toolbar.add_item(buffer_search_bar, cx);
|
toolbar.add_item(buffer_search_bar, cx);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue