breadcrumbs.rs

  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}