breadcrumbs.rs

 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}