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