1use std::any::Any;
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4use std::time::Duration;
5
6use anathema_state::{State, StateId, Value as StateValue};
7use anathema_store::slab::Slab;
8use anathema_templates::strings::{StringId, Strings};
9use anathema_templates::{AssocEventMapping, ComponentBlueprintId};
10use anathema_value_resolver::{Attributes, ValueKind};
11use deferred::DeferredComponents;
12use flume::SendError;
13
14use self::events::{Event, KeyEvent, MouseEvent};
15use crate::WidgetId;
16use crate::layout::Viewport;
17use crate::query::Children;
18use crate::widget::Parent;
19
20pub mod deferred;
21pub mod events;
22
23pub type ComponentFn = dyn Fn() -> Box<dyn AnyComponent>;
24pub type StateFn = dyn FnMut() -> Box<dyn State>;
25
26enum ComponentType {
27 Component(Option<Box<dyn AnyComponent>>, Option<Box<dyn State>>),
28 Prototype(Box<ComponentFn>, Box<StateFn>),
29}
30
31pub struct ComponentRegistry(Slab<ComponentBlueprintId, ComponentType>);
34
35impl ComponentRegistry {
36 pub fn new() -> Self {
37 Self(Slab::empty())
38 }
39
40 pub fn add_component<S: State>(&mut self, id: ComponentBlueprintId, component: impl Component + 'static, state: S) {
44 let comp_type = ComponentType::Component(Some(Box::new(component)), Some(Box::new(state)));
45 self.0.insert_at(id, comp_type);
46 }
47
48 pub fn add_prototype<FC, FS, C, S>(&mut self, id: ComponentBlueprintId, proto: FC, mut state: FS)
49 where
50 FC: 'static + Fn() -> C,
51 FS: 'static + FnMut() -> S,
52 C: Component + 'static,
53 S: State + 'static,
54 {
55 let comp_type =
56 ComponentType::Prototype(Box::new(move || Box::new(proto())), Box::new(move || Box::new(state())));
57
58 self.0.insert_at(id, comp_type);
59 }
60
61 pub fn get(&mut self, id: ComponentBlueprintId) -> Option<(ComponentKind, Box<dyn AnyComponent>, Box<dyn State>)> {
66 match self.0.get_mut(id) {
67 Some(component) => match component {
68 ComponentType::Component(comp, state) => Some((ComponentKind::Instance, comp.take()?, state.take()?)),
69 ComponentType::Prototype(proto, state) => Some((ComponentKind::Prototype, proto(), state())),
70 },
71 None => panic!(),
72 }
73 }
74
75 pub fn return_component(
81 &mut self,
82 id: ComponentBlueprintId,
83 current_component: Box<dyn AnyComponent>,
84 current_state: Box<dyn State>,
85 ) {
86 match self.0.get_mut(id) {
87 Some(component) => match component {
88 ComponentType::Component(comp, state) => {
89 *comp = Some(current_component);
90 *state = Some(current_state);
91 }
92 ComponentType::Prototype(..) => panic!("trying to return a prototype"),
93 },
94 None => panic!(),
95 }
96 }
97}
98
99#[derive(Debug)]
100pub struct ComponentId<T>(pub(crate) ComponentBlueprintId, pub(crate) PhantomData<T>);
101
102impl<T> From<ComponentBlueprintId> for ComponentId<T> {
103 fn from(value: ComponentBlueprintId) -> Self {
104 Self(value, PhantomData)
105 }
106}
107
108impl<T> Clone for ComponentId<T> {
109 fn clone(&self) -> Self {
110 *self
111 }
112}
113
114impl<T> Copy for ComponentId<T> {}
115
116pub struct ViewMessage {
117 pub(super) payload: Box<dyn Any + Send + Sync>,
118 pub(super) recipient: ComponentBlueprintId,
119}
120
121impl ViewMessage {
122 pub fn recipient(&self) -> ComponentBlueprintId {
123 self.recipient
124 }
125
126 pub fn payload(self) -> Box<dyn Any + Send + Sync> {
127 self.payload
128 }
129}
130
131#[derive(Debug, Clone)]
132pub struct Emitter(pub(crate) flume::Sender<ViewMessage>);
133
134impl From<flume::Sender<ViewMessage>> for Emitter {
135 fn from(value: flume::Sender<ViewMessage>) -> Self {
136 Self(value)
137 }
138}
139
140impl Emitter {
141 pub fn emit<T: 'static + Send + Sync>(
142 &self,
143 component_id: ComponentId<T>,
144 value: T,
145 ) -> Result<(), SendError<ViewMessage>> {
146 let msg = ViewMessage {
147 payload: Box::new(value),
148 recipient: component_id.0,
149 };
150 self.0.send(msg)
151 }
152
153 pub async fn emit_async<T: 'static + Send + Sync>(
154 &self,
155 component_id: ComponentId<T>,
156 value: T,
157 ) -> Result<(), SendError<ViewMessage>> {
158 let msg = ViewMessage {
159 payload: Box::new(value),
160 recipient: component_id.0,
161 };
162 self.0.send_async(msg).await
163 }
164}
165
166pub struct Context<'frame, 'bp, T> {
167 inner: AnyComponentContext<'frame, 'bp>,
168 _p: PhantomData<T>,
169}
170
171impl<'frame, 'bp, T: 'static> Context<'frame, 'bp, T> {
172 pub fn new(inner: AnyComponentContext<'frame, 'bp>) -> Self {
173 Self { inner, _p: PhantomData }
174 }
175
176 pub fn publish<D: 'static>(&mut self, ident: &str, data: D) {
183 let Some(parent) = self.parent else { return };
185
186 let Some(ident_id) = self.inner.strings.lookup(ident) else { return };
187
188 let ids = self.assoc_functions.iter().find(|assoc| assoc.internal == ident_id);
189
190 let Some(assoc_event_map) = ids else { return };
191
192 self.inner.assoc_events.push(
193 self.state_id,
194 parent,
195 *assoc_event_map,
196 self.ident_id,
197 self.sender_id,
198 data,
199 );
200 }
201
202 pub fn attribute(&self, key: &str) -> Option<&ValueKind<'_>> {
204 self.attributes.get(key)
205 }
206
207 pub fn emit<M: 'static + Send + Sync>(&self, recipient: ComponentId<M>, value: M) {
209 self.emitter
210 .emit(recipient, value)
211 .expect("this will not fail unless the runtime is droped")
212 }
213}
214
215impl<'frame, 'bp, T> Deref for Context<'frame, 'bp, T> {
216 type Target = AnyComponentContext<'frame, 'bp>;
217
218 fn deref(&self) -> &Self::Target {
219 &self.inner
220 }
221}
222
223impl<'frame, 'bp, T> DerefMut for Context<'frame, 'bp, T> {
224 fn deref_mut(&mut self) -> &mut Self::Target {
225 &mut self.inner
226 }
227}
228
229pub struct AnyComponentContext<'frame, 'bp> {
230 parent: Option<Parent>,
231 ident_id: StringId,
232 sender_id: WidgetId,
233 state_id: StateId,
234 assoc_functions: &'frame [AssocEventMapping],
235 assoc_events: &'frame mut AssociatedEvents,
236 pub attributes: &'frame mut Attributes<'bp>,
237 state: Option<&'frame mut StateValue<Box<dyn State>>>,
238 pub emitter: &'frame Emitter,
239 pub viewport: &'frame Viewport,
240 pub strings: &'frame Strings,
241 pub components: &'frame mut DeferredComponents,
242}
243
244impl<'frame, 'bp> AnyComponentContext<'frame, 'bp> {
245 pub fn new(
246 parent: Option<Parent>,
247 ident_id: StringId,
248 sender_id: WidgetId,
249 state_id: StateId,
250 assoc_functions: &'frame [AssocEventMapping],
251 assoc_events: &'frame mut AssociatedEvents,
252 components: &'frame mut DeferredComponents,
253 attributes: &'frame mut Attributes<'bp>,
254 state: Option<&'frame mut StateValue<Box<dyn State>>>,
255 emitter: &'frame Emitter,
256 viewport: &'frame Viewport,
257 strings: &'frame Strings,
258 ) -> Self {
259 Self {
260 parent,
261 ident_id,
262 sender_id,
263 state_id,
264 assoc_functions,
265 assoc_events,
266 attributes,
267 components,
268 state,
269 emitter,
270 viewport,
271 strings,
272 }
273 }
274
275 pub fn parent(&self) -> Option<Parent> {
276 self.parent
277 }
278}
279
280pub struct AssociatedEvent {
281 pub state: StateId,
282 pub parent: Parent,
283 pub sender: StringId,
284 pub sender_id: WidgetId,
285 event_map: AssocEventMapping,
286 data: Box<dyn Any>,
287}
288
289impl AssociatedEvent {
290 pub fn to_event<'a>(
291 &'a self,
292 internal: &'a str,
293 external: &'a str,
294 sender: &'a str,
295 sender_id: WidgetId,
296 ) -> UserEvent<'a> {
297 UserEvent {
298 external_ident: external,
299 internal_ident: internal,
300 data: &*self.data,
301 sender,
302 sender_id,
303 stop_propagation: false,
304 }
305 }
306
307 pub fn external(&self) -> StringId {
308 self.event_map.external
309 }
310
311 pub fn internal(&self) -> StringId {
312 self.event_map.internal
313 }
314}
315
316#[derive(Debug, Copy, Clone)]
317pub struct UserEvent<'a> {
318 pub sender: &'a str,
319 pub sender_id: WidgetId,
320 pub external_ident: &'a str,
321 pub internal_ident: &'a str,
322 data: &'a dyn Any,
323 stop_propagation: bool,
324}
325
326impl<'a> UserEvent<'a> {
327 pub fn stop_propagation(&mut self) {
328 self.stop_propagation = true;
329 }
330
331 pub fn name(&self) -> &str {
332 self.external_ident
333 }
334
335 pub fn data<T: 'static>(&self) -> &'a T {
341 match self.data.downcast_ref() {
342 Some(data) => data,
343 None => panic!("invalid type when casting event data"),
344 }
345 }
346
347 pub fn data_checked<T: 'static>(&self) -> Option<&'a T> {
349 self.data.downcast_ref()
350 }
351
352 pub fn should_stop_propagation(&self) -> bool {
353 self.stop_propagation
354 }
355}
356
357pub struct AssociatedEvents {
361 inner: Vec<AssociatedEvent>,
362}
363
364impl AssociatedEvents {
365 pub fn new() -> Self {
366 Self { inner: vec![] }
367 }
368
369 fn push<T: 'static>(
370 &mut self,
371 state: StateId,
372 parent: Parent,
373 assoc_event_map: AssocEventMapping,
374 sender: StringId,
375 sender_id: WidgetId,
376 data: T,
377 ) {
378 self.inner.push(AssociatedEvent {
379 state,
380 parent,
381 sender,
382 sender_id,
383 event_map: assoc_event_map,
384 data: Box::new(data),
385 })
386 }
387
388 pub fn next(&mut self) -> Option<AssociatedEvent> {
389 self.inner.pop()
390 }
391}
392
393pub trait Component: 'static {
394 type State: State;
395 type Message;
396
397 const TICKS: bool = true;
398
399 #[allow(unused_variables, unused_mut)]
400 fn on_key(
401 &mut self,
402 key: KeyEvent,
403 state: &mut Self::State,
404 mut children: Children<'_, '_>,
405 mut context: Context<'_, '_, Self::State>,
406 ) {
407 }
408
409 #[allow(unused_variables, unused_mut)]
410 fn on_mount(
411 &mut self,
412 state: &mut Self::State,
413 mut children: Children<'_, '_>,
414 mut context: Context<'_, '_, Self::State>,
415 ) {
416 }
417
418 #[allow(unused_variables, unused_mut)]
419 fn on_unmount(
420 &mut self,
421 state: &mut Self::State,
422 mut children: Children<'_, '_>,
423 mut context: Context<'_, '_, Self::State>,
424 ) {
425 }
426
427 #[allow(unused_variables, unused_mut)]
428 fn on_blur(
429 &mut self,
430 state: &mut Self::State,
431 mut children: Children<'_, '_>,
432 mut context: Context<'_, '_, Self::State>,
433 ) {
434 }
435
436 #[allow(unused_variables, unused_mut)]
437 fn on_focus(
438 &mut self,
439 state: &mut Self::State,
440 mut children: Children<'_, '_>,
441 mut context: Context<'_, '_, Self::State>,
442 ) {
443 }
444
445 #[allow(unused_variables, unused_mut)]
446 fn on_mouse(
447 &mut self,
448 mouse: MouseEvent,
449 state: &mut Self::State,
450 mut children: Children<'_, '_>,
451 mut context: Context<'_, '_, Self::State>,
452 ) {
453 }
454
455 #[allow(unused_variables, unused_mut)]
456 fn on_tick(
457 &mut self,
458 state: &mut Self::State,
459 mut children: Children<'_, '_>,
460 context: Context<'_, '_, Self::State>,
461 dt: Duration,
462 ) {
463 }
464
465 #[allow(unused_variables, unused_mut)]
466 fn on_message(
467 &mut self,
468 message: Self::Message,
469 state: &mut Self::State,
470 mut children: Children<'_, '_>,
471 mut context: Context<'_, '_, Self::State>,
472 ) {
473 }
474
475 #[allow(unused_variables, unused_mut)]
476 fn on_resize(
477 &mut self,
478 state: &mut Self::State,
479 mut children: Children<'_, '_>,
480 mut context: Context<'_, '_, Self::State>,
481 ) {
482 }
483
484 #[allow(unused_variables, unused_mut)]
485 fn on_event(
486 &mut self,
487 event: &mut UserEvent<'_>,
488 state: &mut Self::State,
489 mut children: Children<'_, '_>,
490 mut context: Context<'_, '_, Self::State>,
491 ) {
492 }
493
494 fn accept_focus(&self) -> bool {
495 true
496 }
497}
498
499impl Component for () {
500 type Message = ();
501 type State = ();
502
503 const TICKS: bool = false;
504
505 fn accept_focus(&self) -> bool {
506 false
507 }
508}
509
510#[derive(Debug)]
511pub enum ComponentKind {
512 Instance,
513 Prototype,
514}
515
516pub trait AnyComponent {
517 fn any_event(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, ev: Event) -> Event;
518
519 fn any_message(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>);
520
521 fn any_tick(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, dt: Duration);
522
523 fn any_focus(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
524
525 fn any_blur(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
526
527 fn any_resize(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
528
529 fn any_component_event(
530 &mut self,
531 children: Children<'_, '_>,
532 ctx: AnyComponentContext<'_, '_>,
533 value: &mut UserEvent<'_>,
534 );
535
536 fn any_accept_focus(&self) -> bool;
537
538 fn any_ticks(&self) -> bool;
539}
540
541impl<T> AnyComponent for T
542where
543 T: Component,
544 T: 'static,
545{
546 fn any_event(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, event: Event) -> Event {
547 let mut state = ctx
548 .state
549 .take()
550 .map(|s| s.to_mut_cast::<T::State>())
551 .expect("components always have a state");
552 let context = Context::<T::State>::new(ctx);
553 match event {
554 Event::Blur | Event::Focus => (), Event::Key(ev) => self.on_key(ev, &mut *state, children, context),
556 Event::Mouse(ev) => self.on_mouse(ev, &mut *state, children, context),
557 Event::Tick(dt) => self.on_tick(&mut *state, children, context, dt),
558 Event::Resize(_) => self.on_resize(&mut *state, children, context),
559 Event::Mount => self.on_mount(&mut *state, children, context),
560 Event::Unmount => self.on_unmount(&mut *state, children, context),
561 Event::Noop | Event::Stop => (),
562 }
563 event
564 }
565
566 fn any_accept_focus(&self) -> bool {
567 self.accept_focus()
568 }
569
570 fn any_ticks(&self) -> bool {
571 T::TICKS
572 }
573
574 fn any_message(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>) {
575 let mut state = ctx
576 .state
577 .take()
578 .map(|s| s.to_mut_cast::<T::State>())
579 .expect("components always have a state");
580 let Ok(message) = message.downcast::<T::Message>() else { return };
581 let context = Context::<T::State>::new(ctx);
582 self.on_message(*message, &mut *state, children, context);
583 }
584
585 fn any_focus(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
586 let mut state = ctx
587 .state
588 .take()
589 .map(|s| s.to_mut_cast::<T::State>())
590 .expect("components always have a state");
591 let context = Context::<T::State>::new(ctx);
592 self.on_focus(&mut *state, children, context);
593 }
594
595 fn any_blur(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
596 let mut state = ctx
597 .state
598 .take()
599 .map(|s| s.to_mut_cast::<T::State>())
600 .expect("components always have a state");
601 let context = Context::<T::State>::new(ctx);
602 self.on_blur(&mut *state, children, context);
603 }
604
605 fn any_tick(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, dt: Duration) {
606 let mut state = ctx
607 .state
608 .take()
609 .map(|s| s.to_mut_cast::<T::State>())
610 .expect("components always have a state");
611 let context = Context::<T::State>::new(ctx);
612 self.on_tick(&mut *state, children, context, dt);
613 }
614
615 fn any_resize(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
616 let mut state = ctx
617 .state
618 .take()
619 .map(|s| s.to_mut_cast::<T::State>())
620 .expect("components always have a state");
621 let context = Context::<T::State>::new(ctx);
622 self.on_resize(&mut *state, children, context);
623 }
624
625 fn any_component_event(
626 &mut self,
627 children: Children<'_, '_>,
628 mut ctx: AnyComponentContext<'_, '_>,
629 event: &mut UserEvent<'_>,
630 ) {
631 let mut state = ctx
632 .state
633 .take()
634 .map(|s| s.to_mut_cast::<T::State>())
635 .expect("components always have a state");
636
637 let context = Context::<T::State>::new(ctx);
638
639 self.on_event(event, &mut *state, children, context);
640 }
641}
642
643impl std::fmt::Debug for dyn AnyComponent {
644 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
645 write!(f, "<dyn AnyComponent>")
646 }
647}