1use std::any::Any;
2use std::fmt::{self, Debug};
3use std::ops::ControlFlow;
4
5use anathema_geometry::{Pos, Region, Size};
6use anathema_state::StateId;
7use anathema_store::slab::SecondaryMap;
8use anathema_store::tree::{Tree, TreeView};
9use anathema_templates::ComponentBlueprintId;
10use anathema_value_resolver::AttributeStorage;
11
12pub use self::factory::Factory;
13pub use self::style::{Attributes, Style};
14use crate::WidgetContainer;
15use crate::error::Result;
16use crate::layout::{Constraints, LayoutCtx, PositionCtx, PositionFilter};
17use crate::paint::{PaintCtx, PaintFilter, SizePos};
18pub use crate::tree::{Filter, ForEach, LayoutForEach};
19
20mod factory;
21mod style;
22
23pub type WidgetTreeView<'a, 'bp> = TreeView<'a, WidgetContainer<'bp>>;
24pub type WidgetTree<'a> = Tree<WidgetContainer<'a>>;
25pub type LayoutChildren<'a, 'bp> = LayoutForEach<'a, 'bp>;
26pub type PositionChildren<'a, 'bp> = ForEach<'a, 'bp, PositionFilter>;
27pub type PaintChildren<'a, 'bp> = ForEach<'a, 'bp, PaintFilter>;
28pub type WidgetId = anathema_store::slab::Key;
29
30#[derive(Debug)]
31pub struct CompEntry {
32 pub state_id: StateId,
34 pub widget_id: WidgetId,
36
37 pub accept_ticks: bool,
39
40 component_id: ComponentBlueprintId,
41}
42
43pub struct Components {
45 inner: Vec<CompEntry>,
46}
47
48impl Components {
49 pub fn new() -> Self {
50 Self { inner: vec![] }
51 }
52
53 pub fn push(
54 &mut self,
55 component_id: ComponentBlueprintId,
56 widget_id: WidgetId,
57 state_id: StateId,
58 accept_ticks: bool,
59 ) {
60 let entry = CompEntry {
61 component_id,
62 widget_id,
63 state_id,
64 accept_ticks,
65 };
66
67 self.inner.push(entry)
68 }
69
70 pub fn try_remove(&mut self, widget_id: WidgetId) {
71 self.inner.retain(|entry| entry.widget_id != widget_id);
72 }
73
74 pub fn get(&mut self, index: usize) -> Option<(WidgetId, StateId)> {
76 self.inner.get(index).map(|e| (e.widget_id, e.state_id))
77 }
78
79 pub fn get_by_component_id(&mut self, id: ComponentBlueprintId) -> Option<&CompEntry> {
83 self.inner.iter().find(|e| e.component_id == id)
84 }
85
86 pub fn get_by_widget_id(&mut self, id: WidgetId) -> Option<(WidgetId, StateId)> {
88 self.inner
89 .iter()
90 .find(|entry| entry.widget_id == id)
91 .map(|e| (e.widget_id, e.state_id))
92 }
93
94 pub fn get_ticking(&self, index: usize) -> Option<(WidgetId, StateId)> {
96 self.inner
97 .get(index)
98 .and_then(|e| e.accept_ticks.then_some((e.widget_id, e.state_id)))
99 }
100
101 pub fn iter(&self) -> impl Iterator<Item = &CompEntry> {
102 self.inner.iter()
103 }
104
105 pub fn len(&self) -> usize {
106 self.inner.len()
107 }
108}
109
110#[derive(Debug)]
111pub struct FloatingWidgets(SecondaryMap<WidgetId, WidgetId>);
112
113impl FloatingWidgets {
114 pub fn empty() -> Self {
115 Self(SecondaryMap::empty())
116 }
117
118 pub fn try_remove(&mut self, key: WidgetId) {
119 self.0.try_remove(key);
120 }
121
122 pub(crate) fn insert(&mut self, widget_id: WidgetId) {
123 self.0.insert(widget_id, widget_id);
124 }
125
126 pub fn iter(&self) -> impl Iterator<Item = &WidgetId> {
127 self.0.iter()
128 }
129}
130
131#[derive(Debug, Copy, Clone)]
133pub struct Parent(pub WidgetId);
134
135impl From<Parent> for WidgetId {
136 fn from(value: Parent) -> Self {
137 value.0
138 }
139}
140
141impl From<WidgetId> for Parent {
142 fn from(value: WidgetId) -> Self {
143 Self(value)
144 }
145}
146
147pub struct ComponentParents(SecondaryMap<ComponentBlueprintId, Parent>);
149
150impl ComponentParents {
151 pub fn empty() -> Self {
152 Self(SecondaryMap::empty())
153 }
154
155 pub fn try_remove(&mut self, key: ComponentBlueprintId) {
156 self.0.try_remove(key);
157 }
158
159 pub fn get_parent(&self, child: ComponentBlueprintId) -> Option<Parent> {
160 self.0.get(child).copied()
161 }
162}
163
164pub trait AnyWidget {
167 fn to_any_ref(&self) -> &dyn Any;
168 fn to_any_mut(&mut self) -> &mut dyn Any;
169
170 fn any_layout<'bp>(
171 &mut self,
172 children: LayoutForEach<'_, 'bp>,
173 constraints: Constraints,
174 id: WidgetId,
175 ctx: &mut LayoutCtx<'_, 'bp>,
176 ) -> Result<Size>;
177
178 fn any_position<'bp>(
179 &mut self,
180 children: ForEach<'_, 'bp, PositionFilter>,
181 id: WidgetId,
182 attribute_storage: &AttributeStorage<'bp>,
183 ctx: PositionCtx,
184 );
185
186 fn any_paint<'bp>(
187 &mut self,
188 children: ForEach<'_, 'bp, PaintFilter>,
189 id: WidgetId,
190 attribute_storage: &AttributeStorage<'bp>,
191 ctx: PaintCtx<'_, SizePos>,
192 );
193
194 fn any_floats(&self) -> bool;
195
196 fn any_inner_bounds(&self, pos: Pos, size: Size) -> Region;
197
198 fn any_needs_reflow(&mut self) -> bool;
199}
200
201impl<T: 'static + Widget> AnyWidget for T {
202 fn to_any_ref(&self) -> &dyn Any {
203 self
204 }
205
206 fn to_any_mut(&mut self) -> &mut dyn Any {
207 self
208 }
209
210 fn any_layout<'bp>(
211 &mut self,
212 children: LayoutForEach<'_, 'bp>,
213 constraints: Constraints,
214 id: WidgetId,
215 ctx: &mut LayoutCtx<'_, 'bp>,
216 ) -> Result<Size> {
217 self.layout(children, constraints, id, ctx)
218 }
219
220 fn any_position<'bp>(
221 &mut self,
222 children: ForEach<'_, 'bp, PositionFilter>,
223 id: WidgetId,
224 attribute_storage: &AttributeStorage<'bp>,
225 ctx: PositionCtx,
226 ) {
227 self.position(children, id, attribute_storage, ctx)
228 }
229
230 fn any_paint<'bp>(
231 &mut self,
232 children: ForEach<'_, 'bp, PaintFilter>,
233 id: WidgetId,
234 attribute_storage: &AttributeStorage<'bp>,
235 ctx: PaintCtx<'_, SizePos>,
236 ) {
237 self.paint(children, id, attribute_storage, ctx)
238 }
239
240 fn any_inner_bounds(&self, pos: Pos, size: Size) -> Region {
241 self.inner_bounds(pos, size)
242 }
243
244 fn any_floats(&self) -> bool {
245 self.floats()
246 }
247
248 fn any_needs_reflow(&mut self) -> bool {
249 self.needs_reflow()
250 }
251}
252
253impl Debug for dyn AnyWidget {
254 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255 write!(f, "<dyn AnyWidget>")
256 }
257}
258
259pub trait Widget {
260 fn layout<'bp>(
261 &mut self,
262 children: LayoutForEach<'_, 'bp>,
263 constraints: Constraints,
264 id: WidgetId,
265 ctx: &mut LayoutCtx<'_, 'bp>,
266 ) -> Result<Size>;
267
268 fn paint<'bp>(
269 &mut self,
270 mut children: ForEach<'_, 'bp, PaintFilter>,
271 _id: WidgetId,
272 attribute_storage: &AttributeStorage<'bp>,
273 mut ctx: PaintCtx<'_, SizePos>,
274 ) {
275 _ = children.each(|child, children| {
276 let ctx = ctx.to_unsized();
277 child.paint(children, ctx, attribute_storage);
278 ControlFlow::Continue(())
279 });
280 }
281
282 fn position<'bp>(
283 &mut self,
284 children: ForEach<'_, 'bp, PositionFilter>,
285 id: WidgetId,
286 attribute_storage: &AttributeStorage<'bp>,
287 ctx: PositionCtx,
288 );
289
290 fn floats(&self) -> bool {
291 false
292 }
293
294 fn inner_bounds(&self, pos: Pos, size: Size) -> Region {
295 Region::from((pos, size))
296 }
297
298 fn needs_reflow(&mut self) -> bool {
299 false
300 }
301}
302
303impl Debug for dyn Widget {
304 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
305 write!(f, "<dyn Widget>")
306 }
307}