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 stop_runtime: &'frame mut bool,
243}
244
245impl<'frame, 'bp> AnyComponentContext<'frame, 'bp> {
246 pub fn new(
247 parent: Option<Parent>,
248 ident_id: StringId,
249 sender_id: WidgetId,
250 state_id: StateId,
251 assoc_functions: &'frame [AssocEventMapping],
252 assoc_events: &'frame mut AssociatedEvents,
253 components: &'frame mut DeferredComponents,
254 attributes: &'frame mut Attributes<'bp>,
255 state: Option<&'frame mut StateValue<Box<dyn State>>>,
256 emitter: &'frame Emitter,
257 viewport: &'frame Viewport,
258 stop_runtime: &'frame mut bool,
259 strings: &'frame Strings,
260 ) -> Self {
261 Self {
262 parent,
263 ident_id,
264 sender_id,
265 state_id,
266 assoc_functions,
267 assoc_events,
268 attributes,
269 components,
270 state,
271 emitter,
272 viewport,
273 strings,
274 stop_runtime,
275 }
276 }
277
278 pub fn parent(&self) -> Option<Parent> {
279 self.parent
280 }
281
282 pub fn stop_runtime(&mut self) {
283 *self.stop_runtime = true;
284 }
285}
286
287pub struct AssociatedEvent {
288 pub state: StateId,
289 pub parent: Parent,
290 pub sender: StringId,
291 pub sender_id: WidgetId,
292 event_map: AssocEventMapping,
293 data: Box<dyn Any>,
294}
295
296impl AssociatedEvent {
297 pub fn to_event<'a>(
298 &'a self,
299 internal: &'a str,
300 external: &'a str,
301 sender: &'a str,
302 sender_id: WidgetId,
303 ) -> UserEvent<'a> {
304 UserEvent {
305 external_ident: external,
306 internal_ident: internal,
307 data: &*self.data,
308 sender,
309 sender_id,
310 stop_propagation: false,
311 }
312 }
313
314 pub fn external(&self) -> StringId {
315 self.event_map.external
316 }
317
318 pub fn internal(&self) -> StringId {
319 self.event_map.internal
320 }
321}
322
323#[derive(Debug, Copy, Clone)]
324pub struct UserEvent<'a> {
325 pub sender: &'a str,
326 pub sender_id: WidgetId,
327 pub external_ident: &'a str,
328 pub internal_ident: &'a str,
329 data: &'a dyn Any,
330 stop_propagation: bool,
331}
332
333impl<'a> UserEvent<'a> {
334 pub fn stop_propagation(&mut self) {
335 self.stop_propagation = true;
336 }
337
338 pub fn name(&self) -> &str {
339 self.external_ident
340 }
341
342 pub fn data<T: 'static>(&self) -> &'a T {
348 match self.data.downcast_ref() {
349 Some(data) => data,
350 None => panic!("invalid type when casting event data"),
351 }
352 }
353
354 pub fn data_checked<T: 'static>(&self) -> Option<&'a T> {
356 self.data.downcast_ref()
357 }
358
359 pub fn should_stop_propagation(&self) -> bool {
360 self.stop_propagation
361 }
362}
363
364pub struct AssociatedEvents {
368 inner: Vec<AssociatedEvent>,
369}
370
371impl AssociatedEvents {
372 pub fn new() -> Self {
373 Self { inner: vec![] }
374 }
375
376 fn push<T: 'static>(
377 &mut self,
378 state: StateId,
379 parent: Parent,
380 assoc_event_map: AssocEventMapping,
381 sender: StringId,
382 sender_id: WidgetId,
383 data: T,
384 ) {
385 self.inner.push(AssociatedEvent {
386 state,
387 parent,
388 sender,
389 sender_id,
390 event_map: assoc_event_map,
391 data: Box::new(data),
392 })
393 }
394
395 pub fn next(&mut self) -> Option<AssociatedEvent> {
396 self.inner.pop()
397 }
398}
399
400pub trait Component: 'static {
401 type State: State;
402 type Message;
403
404 const TICKS: bool = true;
405
406 #[allow(unused_variables, unused_mut)]
407 fn on_key(
408 &mut self,
409 key: KeyEvent,
410 state: &mut Self::State,
411 mut children: Children<'_, '_>,
412 mut context: Context<'_, '_, Self::State>,
413 ) {
414 }
415
416 #[allow(unused_variables, unused_mut)]
417 fn on_mount(
418 &mut self,
419 state: &mut Self::State,
420 mut children: Children<'_, '_>,
421 mut context: Context<'_, '_, Self::State>,
422 ) {
423 }
424
425 #[allow(unused_variables, unused_mut)]
426 fn on_unmount(
427 &mut self,
428 state: &mut Self::State,
429 mut children: Children<'_, '_>,
430 mut context: Context<'_, '_, Self::State>,
431 ) {
432 }
433
434 #[allow(unused_variables, unused_mut)]
435 fn on_blur(
436 &mut self,
437 state: &mut Self::State,
438 mut children: Children<'_, '_>,
439 mut context: Context<'_, '_, Self::State>,
440 ) {
441 }
442
443 #[allow(unused_variables, unused_mut)]
444 fn on_focus(
445 &mut self,
446 state: &mut Self::State,
447 mut children: Children<'_, '_>,
448 mut context: Context<'_, '_, Self::State>,
449 ) {
450 }
451
452 #[allow(unused_variables, unused_mut)]
453 fn on_mouse(
454 &mut self,
455 mouse: MouseEvent,
456 state: &mut Self::State,
457 mut children: Children<'_, '_>,
458 mut context: Context<'_, '_, Self::State>,
459 ) {
460 }
461
462 #[allow(unused_variables, unused_mut)]
463 fn on_tick(
464 &mut self,
465 state: &mut Self::State,
466 mut children: Children<'_, '_>,
467 context: Context<'_, '_, Self::State>,
468 dt: Duration,
469 ) {
470 }
471
472 #[allow(unused_variables, unused_mut)]
473 fn on_message(
474 &mut self,
475 message: Self::Message,
476 state: &mut Self::State,
477 mut children: Children<'_, '_>,
478 mut context: Context<'_, '_, Self::State>,
479 ) {
480 }
481
482 #[allow(unused_variables, unused_mut)]
483 fn on_resize(
484 &mut self,
485 state: &mut Self::State,
486 mut children: Children<'_, '_>,
487 mut context: Context<'_, '_, Self::State>,
488 ) {
489 }
490
491 #[allow(unused_variables, unused_mut)]
492 fn on_event(
493 &mut self,
494 event: &mut UserEvent<'_>,
495 state: &mut Self::State,
496 mut children: Children<'_, '_>,
497 mut context: Context<'_, '_, Self::State>,
498 ) {
499 }
500
501 fn accept_focus(&self) -> bool {
502 true
503 }
504}
505
506impl Component for () {
507 type Message = ();
508 type State = ();
509
510 const TICKS: bool = false;
511
512 fn accept_focus(&self) -> bool {
513 false
514 }
515}
516
517#[derive(Debug)]
518pub enum ComponentKind {
519 Instance,
520 Prototype,
521}
522
523pub trait AnyComponent {
524 fn any_event(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, ev: Event) -> Event;
525
526 fn any_message(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>);
527
528 fn any_tick(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>, dt: Duration);
529
530 fn any_focus(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
531
532 fn any_blur(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
533
534 fn any_resize(&mut self, children: Children<'_, '_>, ctx: AnyComponentContext<'_, '_>);
535
536 fn any_component_event(
537 &mut self,
538 children: Children<'_, '_>,
539 ctx: AnyComponentContext<'_, '_>,
540 value: &mut UserEvent<'_>,
541 );
542
543 fn any_accept_focus(&self) -> bool;
544
545 fn any_ticks(&self) -> bool;
546}
547
548impl<T> AnyComponent for T
549where
550 T: Component,
551 T: 'static,
552{
553 fn any_event(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, event: Event) -> Event {
554 let mut state = ctx
555 .state
556 .take()
557 .map(|s| s.to_mut_cast::<T::State>())
558 .expect("components always have a state");
559 let context = Context::<T::State>::new(ctx);
560 match event {
561 Event::Blur | Event::Focus => (), Event::Key(ev) => self.on_key(ev, &mut *state, children, context),
563 Event::Mouse(ev) => self.on_mouse(ev, &mut *state, children, context),
564 Event::Tick(dt) => self.on_tick(&mut *state, children, context, dt),
565 Event::Resize(_) => self.on_resize(&mut *state, children, context),
566 Event::Mount => self.on_mount(&mut *state, children, context),
567 Event::Unmount => self.on_unmount(&mut *state, children, context),
568 Event::Noop | Event::Stop => (),
569 }
570 event
571 }
572
573 fn any_accept_focus(&self) -> bool {
574 self.accept_focus()
575 }
576
577 fn any_ticks(&self) -> bool {
578 T::TICKS
579 }
580
581 fn any_message(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, message: Box<dyn Any>) {
582 let mut state = ctx
583 .state
584 .take()
585 .map(|s| s.to_mut_cast::<T::State>())
586 .expect("components always have a state");
587 let Ok(message) = message.downcast::<T::Message>() else { return };
588 let context = Context::<T::State>::new(ctx);
589 self.on_message(*message, &mut *state, children, context);
590 }
591
592 fn any_focus(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
593 let mut state = ctx
594 .state
595 .take()
596 .map(|s| s.to_mut_cast::<T::State>())
597 .expect("components always have a state");
598 let context = Context::<T::State>::new(ctx);
599 self.on_focus(&mut *state, children, context);
600 }
601
602 fn any_blur(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
603 let mut state = ctx
604 .state
605 .take()
606 .map(|s| s.to_mut_cast::<T::State>())
607 .expect("components always have a state");
608 let context = Context::<T::State>::new(ctx);
609 self.on_blur(&mut *state, children, context);
610 }
611
612 fn any_tick(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>, dt: Duration) {
613 let mut state = ctx
614 .state
615 .take()
616 .map(|s| s.to_mut_cast::<T::State>())
617 .expect("components always have a state");
618 let context = Context::<T::State>::new(ctx);
619 self.on_tick(&mut *state, children, context, dt);
620 }
621
622 fn any_resize(&mut self, children: Children<'_, '_>, mut ctx: AnyComponentContext<'_, '_>) {
623 let mut state = ctx
624 .state
625 .take()
626 .map(|s| s.to_mut_cast::<T::State>())
627 .expect("components always have a state");
628 let context = Context::<T::State>::new(ctx);
629 self.on_resize(&mut *state, children, context);
630 }
631
632 fn any_component_event(
633 &mut self,
634 children: Children<'_, '_>,
635 mut ctx: AnyComponentContext<'_, '_>,
636 event: &mut UserEvent<'_>,
637 ) {
638 let mut state = ctx
639 .state
640 .take()
641 .map(|s| s.to_mut_cast::<T::State>())
642 .expect("components always have a state");
643
644 let context = Context::<T::State>::new(ctx);
645
646 self.on_event(event, &mut *state, children, context);
647 }
648}
649
650impl std::fmt::Debug for dyn AnyComponent {
651 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
652 write!(f, "<dyn AnyComponent>")
653 }
654}