1use std::path::PathBuf;
2
3use gpui2::elements::div::Div;
4
5use crate::{h_stack, theme};
6use crate::{prelude::*, HighlightedText};
7
8#[derive(Clone)]
9pub struct Symbol(pub Vec<HighlightedText>);
10
11#[derive(Element)]
12pub struct Breadcrumb {
13 path: PathBuf,
14 symbols: Vec<Symbol>,
15}
16
17impl Breadcrumb {
18 pub fn new(path: PathBuf, symbols: Vec<Symbol>) -> Self {
19 Self { path, symbols }
20 }
21
22 fn render_separator<V: 'static>(&self, theme: &Theme) -> Div<V> {
23 div()
24 .child(" › ")
25 .text_color(HighlightColor::Default.hsla(theme))
26 }
27
28 fn render<V: 'static>(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
29 let theme = theme(cx);
30
31 let symbols_len = self.symbols.len();
32
33 h_stack()
34 .px_1()
35 // TODO: Read font from theme (or settings?).
36 .font("Zed Mono Extended")
37 .text_sm()
38 .text_color(theme.middle.base.default.foreground)
39 .rounded_md()
40 .hover()
41 .fill(theme.highest.base.hovered.background)
42 .child(self.path.clone().to_str().unwrap().to_string())
43 .child(if !self.symbols.is_empty() {
44 self.render_separator(&theme)
45 } else {
46 div()
47 })
48 .child(
49 div().flex().children(
50 self.symbols
51 .iter()
52 .enumerate()
53 // TODO: Could use something like `intersperse` here instead.
54 .flat_map(|(ix, symbol)| {
55 let mut items =
56 vec![div().flex().children(symbol.0.iter().map(|segment| {
57 div().child(segment.text.clone()).text_color(segment.color)
58 }))];
59
60 let is_last_segment = ix == symbols_len - 1;
61 if !is_last_segment {
62 items.push(self.render_separator(&theme));
63 }
64
65 items
66 })
67 .collect::<Vec<_>>(),
68 ),
69 )
70 }
71}