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