1mod context;
9mod flex;
10mod id;
11mod idle;
12mod mapped;
13#[cfg(test)]
14mod mapped_rules;
15mod memory;
16mod place;
17mod view;
18mod wrap;
19#[cfg(test)]
20mod wrap_rules;
21
22use std::any::{Any, type_name};
23
24pub use context::{EventCx, MeasureCx, PaintCx};
25pub use id::WidgetId;
26pub use view::{NodeMut, View};
27
28pub(crate) use context::{Effects, FocusRequest, Frame, Grounds, Interaction, LayerRecord};
29pub(crate) use flex::{Axis, Flex};
30pub(crate) use id::{IdMap, Key};
31pub(crate) use idle::{IdleScope, IdleWatch};
32pub(crate) use mapped::Reached;
33pub(crate) use memory::Memory;
34
35use mapped::Mapped;
36
37use crate::event::Event;
38use crate::geometry::{Padding, Rect, Size};
39use crate::keymap::Scope;
40
41pub trait Widget<Msg>: 'static {
47 fn measure(&self, cx: &mut MeasureCx<'_>, available: Size) -> Size;
49
50 fn paint(&self, cx: &mut PaintCx<'_>, area: Rect);
52
53 fn paint_overlay(&self, _cx: &mut PaintCx<'_>, _anchor: Rect) {}
56
57 fn event(&self, _cx: &mut EventCx<'_, Msg>, _event: &Event) -> bool {
60 false
61 }
62
63 fn focusable(&self) -> bool {
65 false
66 }
67
68 fn children(&self) -> &[Node<Msg>] {
70 &[]
71 }
72
73 fn children_mut(&mut self) -> &mut [Node<Msg>] {
75 &mut []
76 }
77}
78
79pub(crate) trait StoredWidget<Msg>: Widget<Msg> + Any {}
82
83impl<Msg, W: Widget<Msg>> StoredWidget<Msg> for W {}
84
85pub trait Container<Msg>: Widget<Msg> {
87 fn set_children(&mut self, children: Vec<Node<Msg>>);
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
93pub enum Length {
94 #[default]
96 Auto,
97 Cells(u16),
99 Fill(u16),
101}
102
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
105pub enum Align {
106 #[default]
108 Start,
109 Center,
111 End,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
117pub struct LayoutProps {
118 pub width: Length,
120 pub height: Length,
122 pub padding: Padding,
124 pub gap: u16,
126 pub justify: Align,
128 pub align: Align,
130}
131
132pub struct Node<Msg> {
134 pub(crate) key: Key,
135 pub(crate) id: WidgetId,
136 pub(crate) type_name: &'static str,
137 pub(crate) layout: LayoutProps,
138 pub(crate) persistent: bool,
139 pub(crate) selectable: Option<bool>,
141 pub(crate) actions: Vec<FocusAction<Msg>>,
143 pub(crate) widget: Box<dyn StoredWidget<Msg>>,
144}
145
146pub(crate) struct FocusAction<Msg> {
148 pub(crate) scope: Scope,
149 pub(crate) action: String,
150 pub(crate) message: Box<dyn Fn() -> Msg>,
151}
152
153impl<Msg: 'static> Node<Msg> {
154 pub(crate) fn new<W: Widget<Msg>>(widget: W, index: usize) -> Self {
155 Self {
156 key: Key::Index(index),
157 id: WidgetId::ROOT,
158 type_name: type_name::<W>(),
159 layout: LayoutProps::default(),
160 persistent: false,
161 selectable: None,
162 actions: Vec::new(),
163 widget: Box::new(widget),
164 }
165 }
166
167 #[must_use]
169 pub fn id(&self) -> WidgetId {
170 self.id
171 }
172
173 #[must_use]
175 pub fn layout(&self) -> LayoutProps {
176 self.layout
177 }
178
179 pub(crate) fn answer_action(&self, scope: Scope, action: &str) -> Option<Msg> {
182 self.actions
183 .iter()
184 .find(|answer| answer.scope == scope && answer.action == action)
185 .map(|answer| (answer.message)())
186 }
187
188 pub(crate) fn assign_ids(&mut self, parent: WidgetId) {
190 self.id = parent.child(&self.key, self.type_name);
191 let id = self.id;
192 if let Some(mapped) = (&mut *self.widget as &mut dyn Any).downcast_mut::<Mapped<Msg>>() {
193 mapped.assign_ids(id);
194 return;
195 }
196 for child in self.widget.children_mut() {
197 child.assign_ids(id);
198 }
199 }
200
201 pub(crate) fn find(&self, id: WidgetId) -> Option<Box<dyn Reached<Msg> + '_>> {
204 if self.id == id {
205 return Some(Box::new(self));
206 }
207 if let Some(mapped) = self.mapped() {
208 return mapped.find(id);
209 }
210 self.widget.children().iter().find_map(|child| child.find(id))
211 }
212
213 pub(crate) fn count_focusable(&self) -> usize {
216 let own = usize::from(self.widget.focusable());
217 match self.mapped() {
218 Some(mapped) => own + mapped.count_focusable(),
219 None => own + self.widget.children().iter().map(Self::count_focusable).sum::<usize>(),
220 }
221 }
222
223 fn mapped(&self) -> Option<&Mapped<Msg>> {
225 (&*self.widget as &dyn Any).downcast_ref::<Mapped<Msg>>()
226 }
227}