list.rs

 1mod list_header;
 2mod list_item;
 3mod list_separator;
 4mod list_sub_header;
 5
 6use gpui::{AnyElement, Div};
 7use smallvec::SmallVec;
 8
 9use crate::prelude::*;
10use crate::{v_stack, Label, ToggleState, Toggleable};
11
12pub use list_header::*;
13pub use list_item::*;
14pub use list_separator::*;
15pub use list_sub_header::*;
16
17#[derive(IntoElement)]
18pub struct List {
19    /// Message to display when the list is empty
20    /// Defaults to "No items"
21    empty_message: SharedString,
22    header: Option<ListHeader>,
23    toggle: Toggleable,
24    children: SmallVec<[AnyElement; 2]>,
25}
26
27impl List {
28    pub fn new() -> Self {
29        Self {
30            empty_message: "No items".into(),
31            header: None,
32            toggle: Toggleable::NotToggleable,
33            children: SmallVec::new(),
34        }
35    }
36
37    pub fn empty_message(mut self, empty_message: impl Into<SharedString>) -> Self {
38        self.empty_message = empty_message.into();
39        self
40    }
41
42    pub fn header(mut self, header: ListHeader) -> Self {
43        self.header = Some(header);
44        self
45    }
46
47    pub fn toggle(mut self, toggle: Toggleable) -> Self {
48        self.toggle = toggle;
49        self
50    }
51}
52
53impl ParentElement for List {
54    fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> {
55        &mut self.children
56    }
57}
58
59impl RenderOnce for List {
60    type Rendered = Div;
61
62    fn render(self, _cx: &mut WindowContext) -> Self::Rendered {
63        v_stack()
64            .w_full()
65            .py_1()
66            .children(self.header.map(|header| header))
67            .map(|this| match (self.children.is_empty(), self.toggle) {
68                (false, _) => this.children(self.children),
69                (true, Toggleable::Toggleable(ToggleState::NotToggled)) => this,
70                (true, _) => this.child(Label::new(self.empty_message.clone()).color(Color::Muted)),
71            })
72    }
73}