breadcrumbs.rs

  1use gpui::{
  2    elements::*, AppContext, Entity, RenderContext, Subscription, View, ViewContext, ViewHandle,
  3};
  4use itertools::Itertools;
  5use search::ProjectSearchView;
  6use settings::Settings;
  7use workspace::{
  8    item::{ItemEvent, ItemHandle},
  9    ToolbarItemLocation, ToolbarItemView,
 10};
 11
 12pub enum Event {
 13    UpdateLocation,
 14}
 15
 16pub struct Breadcrumbs {
 17    active_item: Option<Box<dyn ItemHandle>>,
 18    project_search: Option<ViewHandle<ProjectSearchView>>,
 19    subscription: Option<Subscription>,
 20}
 21
 22impl Breadcrumbs {
 23    pub fn new() -> Self {
 24        Self {
 25            active_item: Default::default(),
 26            subscription: Default::default(),
 27            project_search: Default::default(),
 28        }
 29    }
 30}
 31
 32impl Entity for Breadcrumbs {
 33    type Event = Event;
 34}
 35
 36impl View for Breadcrumbs {
 37    fn ui_name() -> &'static str {
 38        "Breadcrumbs"
 39    }
 40
 41    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
 42        let theme = cx.global::<Settings>().theme.clone();
 43        if let Some(breadcrumbs) = self
 44            .active_item
 45            .as_ref()
 46            .and_then(|item| item.breadcrumbs(&theme, cx))
 47        {
 48            Flex::row()
 49                .with_children(Itertools::intersperse_with(breadcrumbs.into_iter(), || {
 50                    Label::new("", theme.breadcrumbs.text.clone()).boxed()
 51                }))
 52                .contained()
 53                .with_style(theme.breadcrumbs.container)
 54                .aligned()
 55                .left()
 56                .boxed()
 57        } else {
 58            Empty::new().boxed()
 59        }
 60    }
 61}
 62
 63impl ToolbarItemView for Breadcrumbs {
 64    fn set_active_pane_item(
 65        &mut self,
 66        active_pane_item: Option<&dyn ItemHandle>,
 67        cx: &mut ViewContext<Self>,
 68    ) -> ToolbarItemLocation {
 69        cx.notify();
 70        self.active_item = None;
 71        self.project_search = None;
 72        if let Some(item) = active_pane_item {
 73            let this = cx.weak_handle();
 74            self.subscription = Some(item.subscribe_to_item_events(
 75                cx,
 76                Box::new(move |event, cx| {
 77                    if let Some(this) = this.upgrade(cx) {
 78                        if let ItemEvent::UpdateBreadcrumbs = event {
 79                            this.update(cx, |_, cx| {
 80                                cx.emit(Event::UpdateLocation);
 81                                cx.notify();
 82                            });
 83                        }
 84                    }
 85                }),
 86            ));
 87            self.active_item = Some(item.boxed_clone());
 88            item.breadcrumb_location(cx)
 89        } else {
 90            ToolbarItemLocation::Hidden
 91        }
 92    }
 93
 94    fn location_for_event(
 95        &self,
 96        _: &Event,
 97        current_location: ToolbarItemLocation,
 98        cx: &AppContext,
 99    ) -> ToolbarItemLocation {
100        if let Some(active_item) = self.active_item.as_ref() {
101            active_item.breadcrumb_location(cx)
102        } else {
103            current_location
104        }
105    }
106}