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}