Skip to main content

ansiq_widgets/
list.rs

1use ansiq_core::{
2    BlockFrame, Element, ElementKind, HighlightSpacing, Layout, Length, Line, ListDirection,
3    ListItem, ListProps, ListState, SelectHandler, Style,
4};
5
6use crate::Block;
7
8pub struct List<Message = ()> {
9    block: Option<BlockFrame>,
10    items: Vec<ListItem>,
11    state: ListState,
12    highlight_symbol: Option<Line>,
13    highlight_style: Style,
14    highlight_spacing: HighlightSpacing,
15    repeat_highlight_symbol: bool,
16    direction: ListDirection,
17    scroll_padding: usize,
18    on_select: Option<SelectHandler<Message>>,
19    layout: Layout,
20    style: Style,
21    focusable: bool,
22}
23
24impl<Message> Default for List<Message> {
25    fn default() -> Self {
26        Self {
27            block: None,
28            items: Vec::new(),
29            state: ListState::default(),
30            highlight_symbol: None,
31            highlight_style: Style::default(),
32            highlight_spacing: HighlightSpacing::WhenSelected,
33            repeat_highlight_symbol: false,
34            direction: ListDirection::TopToBottom,
35            scroll_padding: 0,
36            on_select: None,
37            layout: Layout {
38                width: Length::Fill,
39                height: Length::Auto,
40            },
41            style: Style::default(),
42            focusable: false,
43        }
44    }
45}
46
47impl List<()> {
48    pub fn new<I, T>(items: I) -> Self
49    where
50        I: IntoIterator<Item = T>,
51        T: Into<ListItem>,
52    {
53        Self::default().items(items)
54    }
55}
56
57impl<Message> List<Message> {
58    pub fn block(mut self, block: Block<Message>) -> Self {
59        self.block = Some(block.into_frame());
60        self
61    }
62
63    pub fn item<T>(mut self, item: T) -> Self
64    where
65        T: Into<ListItem>,
66    {
67        self.items.push(item.into());
68        self
69    }
70
71    pub fn items<I, T>(mut self, items: I) -> Self
72    where
73        I: IntoIterator<Item = T>,
74        T: Into<ListItem>,
75    {
76        self.items = items.into_iter().map(Into::into).collect();
77        self
78    }
79
80    pub fn selected(mut self, selected: Option<usize>) -> Self {
81        self.state.select(selected);
82        self
83    }
84
85    pub fn offset(mut self, offset: usize) -> Self {
86        *self.state.offset_mut() = offset;
87        self
88    }
89
90    pub fn state(mut self, state: ListState) -> Self {
91        self.state = state;
92        self
93    }
94
95    pub fn highlight_symbol<L: Into<Line>>(mut self, symbol: L) -> Self {
96        self.highlight_symbol = Some(symbol.into());
97        self
98    }
99
100    pub fn highlight_style<S: Into<Style>>(mut self, style: S) -> Self {
101        self.highlight_style = style.into();
102        self
103    }
104
105    pub fn highlight_spacing(mut self, spacing: HighlightSpacing) -> Self {
106        self.highlight_spacing = spacing;
107        self
108    }
109
110    pub fn repeat_highlight_symbol(mut self, repeat: bool) -> Self {
111        self.repeat_highlight_symbol = repeat;
112        self
113    }
114
115    pub fn direction(mut self, direction: ListDirection) -> Self {
116        self.direction = direction;
117        self
118    }
119
120    pub fn scroll_padding(mut self, padding: usize) -> Self {
121        self.scroll_padding = padding;
122        self
123    }
124
125    pub fn on_select<NextMessage, F>(self, handler: F) -> List<NextMessage>
126    where
127        F: FnMut(usize) -> Option<NextMessage> + 'static,
128    {
129        List {
130            block: self.block,
131            items: self.items,
132            state: self.state,
133            highlight_symbol: self.highlight_symbol,
134            highlight_style: self.highlight_style,
135            highlight_spacing: self.highlight_spacing,
136            repeat_highlight_symbol: self.repeat_highlight_symbol,
137            direction: self.direction,
138            scroll_padding: self.scroll_padding,
139            on_select: Some(std::boxed::Box::new(handler)),
140            layout: self.layout,
141            style: self.style,
142            focusable: true,
143        }
144    }
145
146    pub fn layout(mut self, layout: Layout) -> Self {
147        self.layout = layout;
148        self
149    }
150
151    pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
152        self.style = style.into();
153        self
154    }
155
156    pub fn len(&self) -> usize {
157        self.items.len()
158    }
159
160    pub fn is_empty(&self) -> bool {
161        self.items.is_empty()
162    }
163
164    pub fn build(self) -> Element<Message> {
165        Element::new(ElementKind::List(ListProps {
166            block: self.block,
167            items: self.items,
168            state: self.state,
169            highlight_symbol: self.highlight_symbol,
170            highlight_style: self.highlight_style,
171            highlight_spacing: self.highlight_spacing,
172            repeat_highlight_symbol: self.repeat_highlight_symbol,
173            direction: self.direction,
174            scroll_padding: self.scroll_padding,
175            on_select: self.on_select,
176        }))
177        .with_layout(self.layout)
178        .with_style(self.style)
179        .with_focusable(self.focusable)
180    }
181}
182
183impl<Item> FromIterator<Item> for List<()>
184where
185    Item: Into<ListItem>,
186{
187    fn from_iter<Iter: IntoIterator<Item = Item>>(iter: Iter) -> Self {
188        Self::new(iter)
189    }
190}