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}