1use crate::Event;
2use crate::{buffer::Buffer, Cmd};
3pub use button::Button;
4pub use checkbox::Checkbox;
5use expanse::result::Layout;
6use expanse::{
7 node::{Node, Stretch},
8 style::Style,
9};
10pub use flex_box::FlexBox;
11pub use group_box::GroupBox;
12pub use image_control::Image;
13pub use link::Link;
14pub use list_box::ListBox;
15pub use radio::Radio;
16pub use slider::Slider;
17use std::{any::Any, fmt};
18pub use tab_box::TabBox;
19pub use text_area::TextArea;
20pub use text_input::TextInput;
21pub use text_label::TextLabel;
22
23mod button;
24mod checkbox;
25mod flex_box;
26mod group_box;
27mod image_control;
28mod link;
29mod list_box;
30mod radio;
31mod slider;
32mod tab_box;
33mod text_area;
34mod text_input;
35mod text_label;
36
37pub trait Widget<MSG>
39where
40 Self: fmt::Debug,
41{
42 fn style(&self) -> Style;
44
45 fn layout(&self) -> Option<&Layout>;
47
48 fn get_offset(&self) -> (f32, f32) {
51 (0.0, 0.0)
52 }
53
54 fn set_layout(&mut self, layout: Layout);
55
56 fn add_child(&mut self, _child: Box<dyn Widget<MSG>>) -> bool {
59 false
60 }
61
62 fn children(&self) -> Option<&[Box<dyn Widget<MSG>>]> {
64 None
65 }
66
67 fn children_mut(&mut self) -> Option<&mut [Box<dyn Widget<MSG>>]> {
69 None
70 }
71
72 fn child_mut(
74 &mut self,
75 _index: usize,
76 ) -> Option<&mut Box<dyn Widget<MSG>>> {
77 None
78 }
79
80 fn draw(&self, but: &mut Buffer) -> Vec<Cmd>;
84
85 fn style_node(&self, stretch: &mut Stretch) -> Option<Node> {
88 let children_styles = if let Some(children) = self.children() {
89 children
90 .iter()
91 .filter_map(|c| c.style_node(stretch))
92 .collect()
93 } else {
94 vec![]
95 };
96 stretch.new_node(self.style(), &children_styles).ok()
97 }
98
99 fn set_focused(&mut self, _focused: bool) {}
101
102 fn as_any(&self) -> &dyn Any;
104
105 fn as_any_mut(&mut self) -> &mut dyn Any;
107
108 fn set_size(&mut self, width: Option<f32>, height: Option<f32>);
110
111 fn as_mut(&mut self) -> Option<&mut Self>
113 where
114 Self: Sized + 'static,
115 {
116 self.as_any_mut().downcast_mut::<Self>()
117 }
118
119 fn process_event(&mut self, _event: Event) -> Vec<MSG> {
121 vec![]
122 }
123
124 fn take_child(&mut self, _index: usize) -> Option<Box<dyn Widget<MSG>>> {
126 None
127 }
128
129 fn set_id(&mut self, id: &str);
131
132 fn get_id(&self) -> &Option<String>;
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use crate::*;
140 use expanse::{geometry::*, number::Number};
141 use std::boxed;
142
143 #[test]
144 fn layout() {
145 let mut control = FlexBox::<()>::new();
146 control.horizontal();
147 let mut btn = Button::<()>::new("Hello");
148 btn.set_size(Some(30.0), Some(34.0));
149
150 control.add_child(boxed::Box::new(btn));
151
152 let mut btn = Button::<()>::new("world");
153 btn.set_size(Some(20.0), Some(10.0));
154 control.add_child(boxed::Box::new(btn));
155
156 crate::layout::compute_node_layout(
157 &mut control,
158 Size {
159 width: Number::Defined(100.0),
160 height: Number::Defined(100.0),
161 },
162 );
163
164 let layout1 = control.children().expect("must have children")[1]
165 .layout()
166 .expect("must have layout");
167 assert_eq!(
168 layout1.size,
169 Size {
170 width: 20.0,
171 height: 10.0
172 }
173 );
174
175 assert_eq!(layout1.location, Point { x: 30.0, y: 0.0 });
176 }
177
178 #[test]
179 fn layout2() {
180 let mut control = FlexBox::<()>::new();
181 control.vertical();
182
183 let mut btn1 = Button::<()>::new("Hello");
184 btn1.set_size(Some(100.0), Some(20.0));
185
186 control.add_child(boxed::Box::new(btn1));
187
188 let mut btn2 = Button::<()>::new("world");
189 btn2.set_size(Some(20.0), Some(10.0));
190
191 let mut btn3 = Button::<()>::new("world");
192 btn3.set_size(Some(20.0), Some(10.0));
193
194 let mut hrow = FlexBox::<()>::new();
195 hrow.horizontal();
196
197 hrow.add_child(boxed::Box::new(btn2));
198 hrow.add_child(boxed::Box::new(btn3));
199
200 control.add_child(boxed::Box::new(hrow));
201
202 crate::layout::compute_node_layout(
203 &mut control,
204 Size {
205 width: Number::Defined(100.0),
206 height: Number::Defined(100.0),
207 },
208 );
209
210 let layout_btn2 = control.children().expect("must have children")[1]
211 .children()
212 .expect("must have grand children")[1]
213 .layout()
214 .expect("must have a layout");
215 assert_eq!(layout_btn2.location, Point { x: 20.0, y: 17.0 });
216 }
217}