1use crate::canvas::Canvas;
2use crate::draw::{Draw, DrawResult};
3use crate::event::Event;
4use crate::widget::{Rectangle, Widget};
5
6pub struct Stack<'a, Message = ()> {
8 inner: Vec<Box<dyn Widget<Message> + 'a>>,
9}
10
11impl<'a, Message> Stack<'a, Message> {
12 pub fn new() -> Self {
13 Self { inner: vec![] }
14 }
15
16 pub fn top(mut self, widget: impl Widget<Message> + 'a) -> Self {
17 self.inner.push(Box::new(widget));
18 self
19 }
20
21 pub fn bottom(mut self, widget: impl Widget<Message> + 'a) -> Self {
22 self.inner.insert(0, Box::new(widget));
23 self
24 }
25}
26
27impl<'a, Message> Draw for Stack<'a, Message> {
28 fn draw(&self, canvas: &mut dyn Canvas) -> DrawResult<()> {
29 for widget in self.inner.iter() {
30 widget.draw(canvas)?
31 }
32
33 Ok(())
34 }
35 fn draw_mut(&mut self, canvas: &mut dyn Canvas) -> DrawResult<()> {
36 for widget in self.inner.iter_mut() {
37 widget.draw_mut(canvas)?
38 }
39
40 Ok(())
41 }
42}
43
44impl<'a, Message> Widget<Message> for Stack<'a, Message> {
45 fn size_hint(&self) -> (Option<usize>, Option<usize>) {
46 let width = self
48 .inner
49 .iter()
50 .map(|widget| widget.size_hint().0)
51 .max()
52 .unwrap_or(None);
53 let height = self
54 .inner
55 .iter()
56 .map(|widget| widget.size_hint().1)
57 .max()
58 .unwrap_or(None);
59 (width, height)
60 }
61
62 fn on_event(&self, event: Event, rect: Rectangle) -> Vec<Message> {
63 for widget in self.inner.iter().rev() {
65 let message = widget.on_event(event, rect);
66 if !message.is_empty() {
67 return message;
68 }
69 }
70 vec![]
71 }
72
73 fn on_event_mut(&mut self, event: Event, rect: Rectangle) -> Vec<Message> {
74 for widget in self.inner.iter_mut().rev() {
76 let message = widget.on_event_mut(event, rect);
77 if !message.is_empty() {
78 return message;
79 }
80 }
81 vec![]
82 }
83}
84
85#[cfg(test)]
86#[allow(dead_code)]
87mod test {
88 use super::*;
89 use crate::cell::Cell;
90 use std::sync::Mutex;
91
92 struct WinHint {
93 pub width_hint: Option<usize>,
94 pub height_hint: Option<usize>,
95 }
96
97 impl Draw for WinHint {
98 fn draw(&self, _canvas: &mut dyn Canvas) -> DrawResult<()> {
99 unimplemented!()
100 }
101 }
102
103 impl Widget for WinHint {
104 fn size_hint(&self) -> (Option<usize>, Option<usize>) {
105 (self.width_hint, self.height_hint)
106 }
107 }
108
109 #[test]
110 fn size_hint() {
111 let stack = Stack::new().top(WinHint {
112 width_hint: None,
113 height_hint: None,
114 });
115 assert_eq!((None, None), stack.size_hint());
116
117 let stack = Stack::new().top(WinHint {
118 width_hint: Some(1),
119 height_hint: Some(1),
120 });
121 assert_eq!((Some(1), Some(1)), stack.size_hint());
122
123 let stack = Stack::new()
124 .top(WinHint {
125 width_hint: Some(1),
126 height_hint: Some(2),
127 })
128 .top(WinHint {
129 width_hint: Some(2),
130 height_hint: Some(1),
131 });
132 assert_eq!((Some(2), Some(2)), stack.size_hint());
133
134 let stack = Stack::new()
135 .top(WinHint {
136 width_hint: None,
137 height_hint: None,
138 })
139 .top(WinHint {
140 width_hint: Some(2),
141 height_hint: Some(1),
142 });
143 assert_eq!((Some(2), Some(1)), stack.size_hint());
144 }
145
146 #[derive(PartialEq, Debug)]
147 enum Called {
148 No,
149 Mut,
150 Immut,
151 }
152
153 struct Drawn {
154 called: Mutex<Called>,
155 }
156
157 impl Draw for Drawn {
158 fn draw(&self, _canvas: &mut dyn Canvas) -> DrawResult<()> {
159 *self.called.lock().unwrap() = Called::Immut;
160 Ok(())
161 }
162 fn draw_mut(&mut self, _canvas: &mut dyn Canvas) -> DrawResult<()> {
163 *self.called.lock().unwrap() = Called::Mut;
164 Ok(())
165 }
166 }
167
168 impl Widget for Drawn {}
169
170 #[derive(Default)]
171 struct TestCanvas {}
172
173 #[allow(unused_variables)]
174 impl Canvas for TestCanvas {
175 fn size(&self) -> crate::Result<(usize, usize)> {
176 Ok((100, 100))
177 }
178
179 fn clear(&mut self) -> crate::Result<()> {
180 unimplemented!()
181 }
182
183 fn put_cell(&mut self, row: usize, col: usize, cell: Cell) -> crate::Result<usize> {
184 Ok(1)
185 }
186
187 fn set_cursor(&mut self, row: usize, col: usize) -> crate::Result<()> {
188 unimplemented!()
189 }
190
191 fn show_cursor(&mut self, show: bool) -> crate::Result<()> {
192 unimplemented!()
193 }
194 }
195
196 #[test]
197 fn mutable_widget() {
198 let mut canvas = TestCanvas::default();
199
200 let mut mutable = Drawn {
201 called: Mutex::new(Called::No),
202 };
203 {
204 let mut stack = Stack::new().top(&mut mutable);
205 let _ = stack.draw_mut(&mut canvas).unwrap();
206 }
207 assert_eq!(Called::Mut, *mutable.called.lock().unwrap());
208
209 let immutable = Drawn {
210 called: Mutex::new(Called::No),
211 };
212 let stack = Stack::new().top(&immutable);
213 let _ = stack.draw(&mut canvas).unwrap();
214 assert_eq!(Called::Immut, *immutable.called.lock().unwrap());
215 }
216}