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