1mod context;
9mod flex;
10mod id;
11mod idle;
12mod mapped;
13#[cfg(test)]
14mod mapped_rules;
15mod memory;
16mod place;
17mod view;
18
19use std::any::{Any, type_name};
20
21pub use context::{EventCx, MeasureCx, PaintCx};
22pub use id::WidgetId;
23pub use view::{NodeMut, View};
24
25pub(crate) use context::{Effects, FocusRequest, Frame, Grounds, Interaction, LayerRecord};
26pub(crate) use flex::{Axis, Flex};
27pub(crate) use id::{IdMap, Key};
28pub(crate) use idle::{IdleScope, IdleWatch};
29pub(crate) use mapped::Reached;
30pub(crate) use memory::Memory;
31
32use mapped::Mapped;
33
34use crate::event::Event;
35use crate::geometry::{Padding, Rect, Size};
36use crate::keymap::Scope;
37
38pub trait Widget<Msg>: 'static {
44 fn measure(&self, cx: &mut MeasureCx<'_>, available: Size) -> Size;
46
47 fn paint(&self, cx: &mut PaintCx<'_>, area: Rect);
49
50 fn paint_overlay(&self, _cx: &mut PaintCx<'_>, _anchor: Rect) {}
53
54 fn event(&self, _cx: &mut EventCx<'_, Msg>, _event: &Event) -> bool {
57 false
58 }
59
60 fn focusable(&self) -> bool {
62 false
63 }
64
65 fn children(&self) -> &[Node<Msg>] {
67 &[]
68 }
69
70 fn children_mut(&mut self) -> &mut [Node<Msg>] {
72 &mut []
73 }
74}
75
76pub(crate) trait StoredWidget<Msg>: Widget<Msg> + Any {}
79
80impl<Msg, W: Widget<Msg>> StoredWidget<Msg> for W {}
81
82pub trait Container<Msg>: Widget<Msg> {
84 fn set_children(&mut self, children: Vec<Node<Msg>>);
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
90pub enum Length {
91 #[default]
93 Auto,
94 Cells(u16),
96 Fill(u16),
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
102pub enum Align {
103 #[default]
105 Start,
106 Center,
108 End,
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
114pub struct LayoutProps {
115 pub width: Length,
117 pub height: Length,
119 pub padding: Padding,
121 pub gap: u16,
123 pub justify: Align,
125 pub align: Align,
127}
128
129pub struct Node<Msg> {
131 pub(crate) key: Key,
132 pub(crate) id: WidgetId,
133 pub(crate) type_name: &'static str,
134 pub(crate) layout: LayoutProps,
135 pub(crate) persistent: bool,
136 pub(crate) selectable: Option<bool>,
138 pub(crate) actions: Vec<FocusAction<Msg>>,
140 pub(crate) widget: Box<dyn StoredWidget<Msg>>,
141}
142
143pub(crate) struct FocusAction<Msg> {
145 pub(crate) scope: Scope,
146 pub(crate) action: String,
147 pub(crate) message: Box<dyn Fn() -> Msg>,
148}
149
150impl<Msg: 'static> Node<Msg> {
151 pub(crate) fn new<W: Widget<Msg>>(widget: W, index: usize) -> Self {
152 Self {
153 key: Key::Index(index),
154 id: WidgetId::ROOT,
155 type_name: type_name::<W>(),
156 layout: LayoutProps::default(),
157 persistent: false,
158 selectable: None,
159 actions: Vec::new(),
160 widget: Box::new(widget),
161 }
162 }
163
164 #[must_use]
166 pub fn id(&self) -> WidgetId {
167 self.id
168 }
169
170 #[must_use]
172 pub fn layout(&self) -> LayoutProps {
173 self.layout
174 }
175
176 pub(crate) fn answer_action(&self, scope: Scope, action: &str) -> Option<Msg> {
179 self.actions
180 .iter()
181 .find(|answer| answer.scope == scope && answer.action == action)
182 .map(|answer| (answer.message)())
183 }
184
185 pub(crate) fn assign_ids(&mut self, parent: WidgetId) {
187 self.id = parent.child(&self.key, self.type_name);
188 let id = self.id;
189 if let Some(mapped) = (&mut *self.widget as &mut dyn Any).downcast_mut::<Mapped<Msg>>() {
190 mapped.assign_ids(id);
191 return;
192 }
193 for child in self.widget.children_mut() {
194 child.assign_ids(id);
195 }
196 }
197
198 pub(crate) fn find(&self, id: WidgetId) -> Option<Box<dyn Reached<Msg> + '_>> {
201 if self.id == id {
202 return Some(Box::new(self));
203 }
204 if let Some(mapped) = self.mapped() {
205 return mapped.find(id);
206 }
207 self.widget.children().iter().find_map(|child| child.find(id))
208 }
209
210 pub(crate) fn count_focusable(&self) -> usize {
213 let own = usize::from(self.widget.focusable());
214 match self.mapped() {
215 Some(mapped) => own + mapped.count_focusable(),
216 None => own + self.widget.children().iter().map(Self::count_focusable).sum::<usize>(),
217 }
218 }
219
220 fn mapped(&self) -> Option<&Mapped<Msg>> {
222 (&*self.widget as &dyn Any).downcast_ref::<Mapped<Msg>>()
223 }
224}