1mod context;
9mod flex;
10mod id;
11mod idle;
12mod mapped;
13#[cfg(test)]
14mod mapped_rules;
15mod memory;
16mod view;
17
18use std::any::{Any, type_name};
19
20pub use context::{EventCx, MeasureCx, PaintCx};
21pub use id::WidgetId;
22pub use view::{NodeMut, View};
23
24pub(crate) use context::{Effects, FocusRequest, Frame, Interaction, LayerRecord};
25pub(crate) use flex::{Axis, Flex};
26pub(crate) use id::{IdMap, Key};
27pub(crate) use idle::{IdleScope, IdleWatch};
28pub(crate) use mapped::Reached;
29pub(crate) use memory::Memory;
30
31use mapped::Mapped;
32
33use crate::event::Event;
34use crate::geometry::{Padding, Rect, Size};
35
36pub trait Widget<Msg>: 'static {
42 fn measure(&self, cx: &mut MeasureCx<'_>, available: Size) -> Size;
44
45 fn paint(&self, cx: &mut PaintCx<'_>, area: Rect);
47
48 fn paint_overlay(&self, _cx: &mut PaintCx<'_>, _anchor: Rect) {}
51
52 fn event(&self, _cx: &mut EventCx<'_, Msg>, _event: &Event) -> bool {
55 false
56 }
57
58 fn focusable(&self) -> bool {
60 false
61 }
62
63 fn children(&self) -> &[Node<Msg>] {
65 &[]
66 }
67
68 fn children_mut(&mut self) -> &mut [Node<Msg>] {
70 &mut []
71 }
72}
73
74pub(crate) trait StoredWidget<Msg>: Widget<Msg> + Any {}
77
78impl<Msg, W: Widget<Msg>> StoredWidget<Msg> for W {}
79
80pub trait Container<Msg>: Widget<Msg> {
82 fn set_children(&mut self, children: Vec<Node<Msg>>);
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
88pub enum Length {
89 #[default]
91 Auto,
92 Cells(u16),
94 Fill(u16),
96}
97
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
100pub enum Align {
101 #[default]
103 Start,
104 Center,
106 End,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
112pub struct LayoutProps {
113 pub width: Length,
115 pub height: Length,
117 pub padding: Padding,
119 pub gap: u16,
121 pub justify: Align,
123 pub align: Align,
125}
126
127pub struct Node<Msg> {
129 pub(crate) key: Key,
130 pub(crate) id: WidgetId,
131 pub(crate) type_name: &'static str,
132 pub(crate) layout: LayoutProps,
133 pub(crate) persistent: bool,
134 pub(crate) selectable: Option<bool>,
136 pub(crate) widget: Box<dyn StoredWidget<Msg>>,
137}
138
139impl<Msg: 'static> Node<Msg> {
140 pub(crate) fn new<W: Widget<Msg>>(widget: W, index: usize) -> Self {
141 Self {
142 key: Key::Index(index),
143 id: WidgetId::ROOT,
144 type_name: type_name::<W>(),
145 layout: LayoutProps::default(),
146 persistent: false,
147 selectable: None,
148 widget: Box::new(widget),
149 }
150 }
151
152 #[must_use]
154 pub fn id(&self) -> WidgetId {
155 self.id
156 }
157
158 #[must_use]
160 pub fn layout(&self) -> LayoutProps {
161 self.layout
162 }
163
164 pub(crate) fn assign_ids(&mut self, parent: WidgetId) {
166 self.id = parent.child(&self.key, self.type_name);
167 let id = self.id;
168 if let Some(mapped) = (&mut *self.widget as &mut dyn Any).downcast_mut::<Mapped<Msg>>() {
169 mapped.assign_ids(id);
170 return;
171 }
172 for child in self.widget.children_mut() {
173 child.assign_ids(id);
174 }
175 }
176
177 pub(crate) fn find(&self, id: WidgetId) -> Option<Box<dyn Reached<Msg> + '_>> {
180 if self.id == id {
181 return Some(Box::new(self));
182 }
183 if let Some(mapped) = self.mapped() {
184 return mapped.find(id);
185 }
186 self.widget.children().iter().find_map(|child| child.find(id))
187 }
188
189 pub(crate) fn count_focusable(&self) -> usize {
192 let own = usize::from(self.widget.focusable());
193 match self.mapped() {
194 Some(mapped) => own + mapped.count_focusable(),
195 None => own + self.widget.children().iter().map(Self::count_focusable).sum::<usize>(),
196 }
197 }
198
199 fn mapped(&self) -> Option<&Mapped<Msg>> {
201 (&*self.widget as &dyn Any).downcast_ref::<Mapped<Msg>>()
202 }
203}