use gpui::{ AnyElement, App, Context, EventEmitter, Font, Global, IntoElement, Render, Subscription, Window, }; use ui::prelude::*; use workspace::{ ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, item::{HighlightedText, ItemEvent, ItemHandle}, }; type RenderBreadcrumbTextFn = fn( Vec, Option, Option, &dyn ItemHandle, bool, &mut Window, &App, ) -> AnyElement; pub struct RenderBreadcrumbText(pub RenderBreadcrumbTextFn); impl Global for RenderBreadcrumbText {} pub struct Breadcrumbs { pane_focused: bool, active_item: Option>, subscription: Option, } impl Default for Breadcrumbs { fn default() -> Self { Self::new() } } impl Breadcrumbs { pub fn new() -> Self { Self { pane_focused: false, active_item: Default::default(), subscription: Default::default(), } } } impl EventEmitter for Breadcrumbs {} impl Render for Breadcrumbs { fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { let element = h_flex() .id("breadcrumb-container") .flex_grow_1() .h_8() .overflow_x_scroll() .text_ui(cx); let Some(active_item) = self.active_item.as_ref() else { return element.into_any_element(); }; let Some((segments, breadcrumb_font)) = active_item.breadcrumbs(cx) else { return element.into_any_element(); }; let prefix_element = active_item.breadcrumb_prefix(window, cx); if let Some(render_fn) = cx.try_global::() { (render_fn.0)( segments, breadcrumb_font, prefix_element, active_item.as_ref(), false, window, cx, ) } else { element.into_any_element() } } } impl ToolbarItemView for Breadcrumbs { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn ItemHandle>, window: &mut Window, cx: &mut Context, ) -> ToolbarItemLocation { cx.notify(); self.active_item = None; let Some(item) = active_pane_item else { return ToolbarItemLocation::Hidden; }; let this = cx.entity().downgrade(); self.subscription = Some(item.subscribe_to_item_events( window, cx, Box::new(move |event, _, cx| { if let ItemEvent::UpdateBreadcrumbs = event { this.update(cx, |this, cx| { cx.notify(); if let Some(active_item) = this.active_item.as_ref() { cx.emit(ToolbarItemEvent::ChangeLocation( active_item.breadcrumb_location(cx), )) } }) .ok(); } }), )); self.active_item = Some(item.boxed_clone()); item.breadcrumb_location(cx) } fn pane_focus_update( &mut self, pane_focused: bool, _window: &mut Window, _: &mut Context, ) { self.pane_focused = pane_focused; } }