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}