1use editor::render_breadcrumb_text;
2use gpui::{Context, EventEmitter, IntoElement, Render, Subscription, Window};
3use theme::ActiveTheme;
4use ui::prelude::*;
5use workspace::{
6 ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
7 item::{ItemEvent, ItemHandle},
8};
9
10pub struct Breadcrumbs {
11 pane_focused: bool,
12 active_item: Option<Box<dyn ItemHandle>>,
13 subscription: Option<Subscription>,
14}
15
16impl Default for Breadcrumbs {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl Breadcrumbs {
23 pub fn new() -> Self {
24 Self {
25 pane_focused: false,
26 active_item: Default::default(),
27 subscription: Default::default(),
28 }
29 }
30}
31
32impl EventEmitter<ToolbarItemEvent> for Breadcrumbs {}
33
34impl Render for Breadcrumbs {
35 fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
36 let element = h_flex()
37 .id("breadcrumb-container")
38 .flex_grow()
39 .h_8()
40 .overflow_x_scroll()
41 .text_ui(cx);
42 let Some(active_item) = self.active_item.as_ref() else {
43 return element.into_any_element();
44 };
45
46 let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else {
47 return element.into_any_element();
48 };
49 let prefix_element = active_item.breadcrumb_prefix(window, cx);
50 render_breadcrumb_text(segments, prefix_element, active_item.as_ref(), window, cx)
51 .into_any_element()
52 }
53}
54
55impl ToolbarItemView for Breadcrumbs {
56 fn set_active_pane_item(
57 &mut self,
58 active_pane_item: Option<&dyn ItemHandle>,
59 window: &mut Window,
60 cx: &mut Context<Self>,
61 ) -> ToolbarItemLocation {
62 cx.notify();
63 self.active_item = None;
64
65 let Some(item) = active_pane_item else {
66 return ToolbarItemLocation::Hidden;
67 };
68
69 let this = cx.entity().downgrade();
70 self.subscription = Some(item.subscribe_to_item_events(
71 window,
72 cx,
73 Box::new(move |event, _, cx| {
74 if let ItemEvent::UpdateBreadcrumbs = event {
75 this.update(cx, |this, cx| {
76 cx.notify();
77 if let Some(active_item) = this.active_item.as_ref() {
78 cx.emit(ToolbarItemEvent::ChangeLocation(
79 active_item.breadcrumb_location(cx),
80 ))
81 }
82 })
83 .ok();
84 }
85 }),
86 ));
87 self.active_item = Some(item.boxed_clone());
88 item.breadcrumb_location(cx)
89 }
90
91 fn pane_focus_update(
92 &mut self,
93 pane_focused: bool,
94 _window: &mut Window,
95 _: &mut Context<Self>,
96 ) {
97 self.pane_focused = pane_focused;
98 }
99}