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
43 let Some(active_item) = self.active_item.as_ref() else {
44 return element.into_any_element();
45 };
46
47 let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else {
48 return element.into_any_element();
49 };
50
51 let prefix_element = active_item.breadcrumb_prefix(window, cx);
52
53 render_breadcrumb_text(
54 segments,
55 prefix_element,
56 active_item.as_ref(),
57 false,
58 window,
59 cx,
60 )
61 .into_any_element()
62 }
63}
64
65impl ToolbarItemView for Breadcrumbs {
66 fn set_active_pane_item(
67 &mut self,
68 active_pane_item: Option<&dyn ItemHandle>,
69 window: &mut Window,
70 cx: &mut Context<Self>,
71 ) -> ToolbarItemLocation {
72 cx.notify();
73 self.active_item = None;
74
75 let Some(item) = active_pane_item else {
76 return ToolbarItemLocation::Hidden;
77 };
78
79 let this = cx.entity().downgrade();
80 self.subscription = Some(item.subscribe_to_item_events(
81 window,
82 cx,
83 Box::new(move |event, _, cx| {
84 if let ItemEvent::UpdateBreadcrumbs = event {
85 this.update(cx, |this, cx| {
86 cx.notify();
87 if let Some(active_item) = this.active_item.as_ref() {
88 cx.emit(ToolbarItemEvent::ChangeLocation(
89 active_item.breadcrumb_location(cx),
90 ))
91 }
92 })
93 .ok();
94 }
95 }),
96 ));
97 self.active_item = Some(item.boxed_clone());
98 item.breadcrumb_location(cx)
99 }
100
101 fn pane_focus_update(
102 &mut self,
103 pane_focused: bool,
104 _window: &mut Window,
105 _: &mut Context<Self>,
106 ) {
107 self.pane_focused = pane_focused;
108 }
109}